2012-07-04 28 views
8

có lẽ đây là dễ dàng, nhưng tìm kiếm nó trên mạng Internet đã cho tôi đau đầuLâu đài Windsor - Làm thế nào để lập bản đồ dụ đặt tên trong constructor injection

đây là vấn đề:

interface IValidator 
{ 
    void Validate(object obj); 
} 

public class ValidatorA : IValidator 
{ 
    public void Validate(object obj) { } 
} 

public class ValidatorB : IValidator 
{ 
    public void Validate(object obj) { } 
} 


interface IClassA { } 
interface IClassB { } 

public class MyBaseClass 
{ 
    protected IValidator validator; 

    public void Validate() 
    { 
     validator.Validate(this); 
    } 
} 

public class ClassA : MyBaseClass, IClassA 
{ 
    //problem: validator should ValidatorA 
    public ClassA(IValidator validator) { } 
} 

public class ClassB : MyBaseClass, IClassB 
{ 
    //problem: validator should ValidatorB 
    public ClassB(IValidator validator) { } 
} 

public class OtherClass 
{ 
    public OtherClass(IClassA a, IClassB b) { } 
} 


//on Main 
var oc = container.Resolve<OtherClass>(); 

Bất kỳ ý tưởng?

EDIT

Tôi đã đăng ký ValidatorAValidatorB với Named, bây giờ vấn đề như thế nào Lâu đài Windsor có thể tiêm những validator đúng với ClassAClassB, là có một cách để làm điều đó? hoặc có giải pháp nào tốt hơn không?

nếu có ai đó nghĩ rằng thiết kế lớp của tôi sai, vui lòng mở bất kỳ lời khuyên nào. Cho đến nay tôi nghĩ rằng nó chính xác. Có, trình xác thực có cấu hình cụ thể cho Lớp cụ thể. nhưng có những lý do được tóm tắt:

  1. Trình xác nhận là một đối tượng phức tạp, đôi khi phải kết nối với cơ sở dữ liệu, vì vậy tôi phải chuyển giao diện thay vì triển khai cho nhà xây dựng vì lý do kiểm tra đơn vị.
  2. Không có cách nào để sử dụng giao diện khác nhau cho bất kỳ Validator, bởi vì phương pháp duy nhất mà tôi sử dụng là Validate
  3. Tôi nghĩ MyBaseClass.Validate() một chung mẫu phương pháp mẫu phải không?
+2

Mô tả sự cố của bạn là trừu tượng. –

+2

Nếu ClassA yêu cầu triển khai cụ thể IValidator, thì thiết kế sai, vì giao diện không cung cấp sự trừu tượng hữu ích. –

+0

@ Jacek Grogon, không có tôi chỉ cần phương thức 'Validate', thực sự có một baseclass ClassA và ClassB được gọi là phương thức' Validate'. nhưng tôi không viết nó ở đây chỉ để che giấu sự phức tạp. – ktutnik

Trả lời

9

Không đi sâu vào các chi tiết của kiến ​​trúc lựa chọn của bạn chỉ tập trung vào cấu hình chứa Windsor:

Nếu bạn đã đăng ký nhiều tên thực hiện một giao diện nhất định (IValidator), bạn có thể chỉ định mà một trong những bạn muốn sử dụng khi đăng ký các lớp tiêu dùng (ClassA, ClassB) với việc sử dụng ServiceOverrides:

các nhà cung cấp cấu hình chứa sau một OtherClass với ClassA dụ với một trường hợp ValidatorAClassB với ValidatorB:

var container = new WindsorContainer(); 

container.Register(Component.For<IClassA>().ImplementedBy<ClassA>() 
    .DependsOn(ServiceOverride.ForKey<IValidator>().Eq("ValidatorA"))); 
container.Register(Component.For<IClassB>().ImplementedBy<ClassB>() 
    .DependsOn(ServiceOverride.ForKey<IValidator>().Eq("ValidatorB"))); 

container.Register(Component.For<IValidator>().ImplementedBy<ValidatorA>() 
    .Named("ValidatorA")); 
container.Register(Component.For<IValidator>().ImplementedBy<ValidatorB>() 
    .Named("ValidatorB")); 

container.Register(Component.For<OtherClass>().ImplementedBy<OtherClass>()); 

var oc = container.Resolve<OtherClass>(); 
+0

cảm ơn bạn, đây là những gì tôi muốn. trường hợp đóng – ktutnik

1

Có vẻ như bạn đang cố gắng để đưa các cặp vợ chồng chặt chẽ (ClassA với ValidatorA, ClassB với ValidatorB) như các loại độc lập vào một container thông thường. Điều này là vô nghĩa. Nếu bạn phải dựa vào khớp nối chặt chẽ như thế này, hãy quên tiêm phụ thuộc trong vấn đề này và chỉ cần tham khảo khó khăn các loại.

Điều này sẽ có ý nghĩa hơn nếu bạn có thể triển khai trình xác thực chung cho tất cả các lớp. Ví dụ: làm cho các lớp chịu trách nhiệm cung cấp quy tắc xác thực và để Validator chỉ thi hành các quy tắc. Hoặc có lẽ chỉ cần bao gồm toàn bộ xác nhận bên trong các lớp học của bạn, đó có lẽ là kịch bản hợp lý nhất ở đây.

MyBaseClass.Validate() giống như đảo ngược kiểm soát, nhưng không giống như phương pháp mẫu.

+0

cảm ơn cho phản ứng, có lớp là cặp đôi thight, nhưng quá trình lặp đi lặp lại, thực sự có các nhiệm vụ trong 'MyBaseClass.Validate()': 1. Lấy các erros từ 'validator.Validate (this)', 2. Dispatch 'DataErrorEvent' 3. Thay đổi thuộc tính' HasError', (Thats lý do tại sao tôi gọi nó là phương thức tempalte) tất cả những nhiệm vụ đó nên được thực hiện theo cách đồng bộ. nó sẽ là một ý tưởng tồi để làm điều đó trong mọi quyền ClassA và ClassB? – ktutnik

+0

Nếu vậy thì '' Validate() '' thực sự là phương thức mẫu. Tuy nhiên, tại sao không đặt phương pháp thành phần, nói '' ValidateCore() '' trong '' ClassA'' và không có trong '' ValidatorA''? Nếu nó lặp đi lặp lại, sau đó đặt nó trong '' MyBaseClass''. Việc giải nén lớp '' Validator'' sẽ làm tăng thêm độ phức tạp và gây trở ngại rõ ràng. –

+0

nếu im không msitaken, bạn có nghĩa là khởi tạo 'ValidatorA' bên trong' ClassA' và tạo phương thức mới 'ValidateCore' sau đó gọi' ValidateCore' từ 'MyBaseClass.Validate()' phải không ?. tôi nghĩ rằng tôi không thể làm điều đó bởi vì nó sẽ không thể làm bài kiểm tra đơn vị, nơi 'ValidatorA' hoặc' ValidatorB' trong mọi trường hợp nên kết nối với cơ sở dữ liệu. – ktutnik

Các vấn đề liên quan