2009-09-08 24 views
36

làm cách nào để đăng ký hai giao diện khác nhau trong Unity với cùng một ví dụ ... Hiện nay tôi đang sử dụngUnity ký hai giao diện như một singleton

 _container.RegisterType<EventService, EventService>(new ContainerControlledLifetimeManager()); 
     _container.RegisterInstance<IEventService>(_container.Resolve<EventService>()); 
     _container.RegisterInstance<IEventServiceInformation>(_container.Resolve<EventService>()); 

mà làm việc, nhưng không nhìn đẹp ..

Vì vậy, tôi nghĩ bạn sẽ có được ý tưởng. EventService thực hiện hai giao diện, tôi muốn tham chiếu đến cùng một đối tượng nếu tôi giải quyết các giao diện.

Chris

+0

OK, nếu đây là con đường để đi, tôi chỉ giữ nó. Chỉ là quan tâm nếu có một cách thanh lịch hơn, nhưng nó đang làm việc, và đó là điểm. Tôi thực sự thích Unity cho đến nay ... khá đẹp khi kết hợp với PRISM –

+0

Hãy xem câu trả lời của Sven ... nó có rất nhiều công đức. Hãy xem các bình luận của @Chris Tavares về câu trả lời của tôi cho một số chi tiết. Kiểm tra xem nó ra và nếu bạn thích nó, tôi muốn bạn đánh dấu một câu trả lời cho người khác. –

Trả lời

13

Sửa

Sau khi một số thông tin phản hồi trong các ý kiến ​​tôi đã quyết định rằng câu trả lời của Sven là một câu trả lời tốt hơn nhiều. Cảm ơn Chris Tavares vì ​​đã chỉ ra những thành tích kỹ thuật.


Đó là cách duy nhất để thực hiện điều đó.

Bạn có thể sửa đổi nó một chút (tôi ghét RegisterType với cùng loại cho mỗi tham số generic):

EventService es = _container.Resolve<EventService>(); 
_container.RegisterInstance<IEventService>(es); 
_container.RegisterInstance<IEventServiceInformation>(es); 

Nếu một hoặc nhiều IoC trẻ em của bạn sẽ yêu cầu các loại bê tông EventService (hy vọng không) bạn sẽ thêm một số khác RegisterInstance loại RegisterInstance<EventService>. Hy vọng rằng bạn không cần điều đó và tất cả các đối tượng phụ thuộc đang yêu cầu IEventService, chứ không phải là EventService.

Hope this helps, Anderson

+5

Thực hành tốt với tiêm phụ thuộc, để tách thời gian nối dây khỏi thời gian phân giải càng nhiều càng tốt. Giải pháp này có nhược điểm là yêu cầu bạn trộn các cuộc gọi đến 'giải quyết' với các cuộc gọi đến 'đăng ký' –

+0

@Nigel Thorne: Nói chung điều đó là đúng, nhưng trong trường hợp này OP có một dịch vụ mà họ cần đăng ký rất nhiều phụ thuộc. Tôi đề nghị Unity tạo đối tượng này để các phụ thuộc đó được tự động giải quyết sao cho thể hiện có thể được sử dụng cho cả hai cuộc gọi Register (anh/cô ấy cần cùng một cá thể được trả về cho cả hai giao diện). Thông thường điều này là không mong muốn, nhưng thực sự là cách duy nhất để làm điều này trong trường hợp này (trừ việc khởi tạo đối tượng theo cách thủ công). –

+3

Điều này thực sự không phải là cách để đi - sử dụng câu trả lời của Sven Kunzler dưới đây để thay thế. –

51

[Chỉnh sửa]

Các giải pháp để thực hiện điều này thông qua cấu hình XML có thể được tìm thấy here. Dựa trên câu trả lời đó, tôi sẽ đề xuất một cách tiếp cận chỉ mã được sắp xếp hợp lý như sau:

_container.RegisterType<IEventService, EventService>(new ContainerControlledLifetimeManager()); 
_container.RegisterType<IEventServiceInformation, EventService>(new ContainerControlledLifetimeManager()); 
bool singleton = ReferenceEquals(_container.Resolve<IEventService>(), _container.Resolve<IEventServiceInformation>()); 

Bằng cách này, lớp EventService không được xuất bản bởi vùng chứa. Vì lớp học nên được coi là một chi tiết thực hiện, đây là cách tiếp cận thích hợp hơn.

[Original câu trả lời]

Một chút muộn một câu trả lời, nhưng nên làm các trick:

_container.RegisterType<EventService>(new ContainerControlledLifetimeManager()); 
_container.RegisterType<IEventService, EventService>(); 
_container.RegisterType<IEventServiceInformation, EventService>(); 

bool singleton = ReferenceEquals(_container.Resolve<IEventService>(), _container.Resolve<IEventServiceInformation>()); 
+0

có ai biết cách thực hiện điều này thông qua cấu hình không? – JML

+0

Tôi cũng muốn biết cách thực hiện điều này thông qua cấu hình. – lukebuehler

+6

Thật thú vị, (ít nhất là ở đây) có vẻ như khi đặt một trong số đó là đăng ký tên nó không hoạt động ... – Reddog

0

Một giải pháp mà cũng có thể làm việc cho các trường hợp được đặt tên là sử dụng Adapter Pattern để tạo ra bộ điều hợp throwaway cho giao diện bao quanh các cá thể đơn. Sau đó, các cá thể được giải quyết sẽ luôn được chuyển hướng đến cá thể singleton, sự kiện nếu chúng được giải quyết bằng cách sử dụng ResolveAll. Điều này giúp khi có một đống các dịch vụ thực hiện một giao diện chung như IStartable hoặc một cái gì đó.

public class EventServiceAdapter<T> : IEventService where T : IEventService 
{ 
    private readonly T _adapted; 
    EventServiceAdapter(T adapted) 
    { 
     _adapted = adapted; 
    } 
    public string SomeMethod() 
    { 
     return _adapted.SomeMethod(); 
    } 
} 

Sau đó đăng ký bộ điều hợp giao diện xung quanh loại đơn đăng ký của bạn.

_container 
    .RegisterType<EventService>(new ContainerControlledLifetimeManager()) 
    .RegisterType<IEventService, EventServiceAdapter<EventService>>("namedEventService"); 

Sau đó, bạn có thể ẩn bất kỳ singleton nào sau bất kỳ số lượng giao diện nào và sử dụng cả Giải quyết và Giải quyết tất cả.

4

Cách tiếp cận bộ tiếp hợp dường như cồng kềnh cho một điều đơn giản như vậy nên tôi nhìn xa hơn một chút. Để giải quyết vấn đề với các trường hợp được đặt tên, bạn cần phải đăng ký loại và đăng ký các nhà máy cho các giao diện.

InjectionFactory factory = new InjectionFactory(x => x.Resolve<SimulationService>()); 
this.Container.RegisterType<SimulationService>(new ContainerControlledLifetimeManager()); 
this.Container.RegisterType<IContentProvider>("SimulationContentProvider", factory); 
this.Container.RegisterType<ISimulationService>(factory); 

Bằng cách này bạn không cần phải tạo một thể hiện của lớp bê tông (lúc đăng ký) mà không thể xảy ra trong trường hợp của tôi do thiếu phụ thuộc.

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