2011-11-18 40 views
10

Mục tiêu của tôi là tạo hàm tiêm một mảng các đối tượng thực hiện một giao diện.Tiêm mảng với Unity

Sau đây là cách tôi hiện có.

  Container 

        .RegisterInstance<Company>(ParseCompany(args[1]) 

        .RegisterInstance<eTargets>(ParseTargets(args[2])) 

        .RegisterInstance<ILoader[]>(new ILoader[] { 
         Container.Resolve<CustomerLoader>(), 
         Container.Resolve<PaymentLoader(), 
         Container.Resolve<InvoiceLoader() 
        }); 

Có phải điển hình để gọi Giải quyết trong cấu hình vùng chứa theo cách này hoặc có cách nào tiêu chuẩn hơn để thực hiện điều tương tự không?

Trả lời

25

Thống nhất tự nhiên hiểu mảng, vì vậy không có lý do gì để làm cho nó trở nên phức tạp. Chỉ cần đăng ký ILoaders bạn muốn bao gồm và giải quyết các đồ thị đối tượng bình thường. Auto-dây sẽ chăm sóc phần còn lại:

container.RegisterType<ILoader, FooLoader>("foo"); 
container.RegisterType<ILoader, BarLoader>("bar"); 
container.RegisterType<ILoader, BazLoader>("baz"); 

var c = container.Resolve<MyConsumer>(); 

giả định rằng các nhà xây dựng MyConsumer được định nghĩa như thế này:

public MyConsumer(ILoader[] loaders) 

Tuy nhiên, bạn nên biết rằng (vì một lý do không thể dò được) Unity chỉ bao gồm có tên là thành phần theo cách này. Các mặc định phần:

container.RegisterType<ILoader, Loader>(); 

sẽ không được đưa vào mảng, vì nó không có tên.

+0

wow, đó là một mẹo tuyệt vời nhờ –

+0

Không chính xác không thể dò được: lý do là, nếu bạn cần nhiều hơn một mục nhập cho cùng loại, sau đó bạn phải thêm một tên khác Unity sẽ nghĩ rằng bạn đang thực sự trọng mục nhập trước đó (bị cấm). –

+3

@BrunoBrant 'unfathomable' vì không có DI Container nào hoạt động như thế. Xem ví dụ [cuốn sách của tôi] (http://amzn.to/12p90MG) để biết thêm chi tiết. –

3

Sử dụng Resolve trong "thời gian cấu hình" có thể chấp nhận được và thường hữu ích, và nó hoàn toàn hợp lệ cho mảng hoặc đếm.

Bạn cũng có thể thực hiện việc trên bằng cách đăng ký loại ILoader[] và đăng ký từng loại cụ thể ILoader bằng cách sử dụng quá tải RegisterType có tên.

Sau đó, bất cứ nơi nào ILoader[] là bắt buộc (ví dụ: cần phải được tiêm), tất cả các điều trên sẽ giải quyết cho bạn sau thời gian cấu hình. Tất nhiên, nếu bạn cần nhiều/khác nhau ILoader[] nó sẽ trở lại cần sử dụng Resolve trong thời gian cấu hình.

1

Nếu bạn có một kịch bản hơi phức tạp hơn khi các mảng giá trị khác nhau phải được sử dụng ở các vị trí khác nhau, thì bạn có thể sử dụng ResolvedArrayParameter, ví dụ:

container.RegisterType<ILoader, FooLoader>("foo"); 
container.RegisterType<ILoader, BarLoader>("bar"); 
container.RegisterType<ILoader, BazLoader>("baz"); 
container.RegisterType<ILoader, BooLoader>("boo"); 

container.RegisterType<IConsumer, MyConsumer>("c1", 
    new InjectionConstructor(
     new ResolvedArrayParameter<ILoader>(
      new ResolvedParameter<ILoader>("foo"), 
      new ResolvedParameter<ILoader>("bar")))); 

container.RegisterType<IConsumer, MyConsumer>("c2", 
    new InjectionConstructor(
     new ResolvedArrayParameter<ILoader>(
      new ResolvedParameter<ILoader>("baz"), 
      new ResolvedParameter<ILoader>("boo")))); 

var c1 = container.Resolve<MyConsumer>("c1"); 
var c1 = container.Resolve<MyConsumer>("c2"); 
Các vấn đề liên quan