2012-02-03 13 views
5

Tôi đã thấy dòng mã này trong một số hướng dẫn để sử dụng Unity trong asp.net mvc3. Tôi đã ấn tượng rằng Service Locator là một mô hình chống mẫu và không phải là thực hành tốt nhất. Là dịch vụ định vị này một cái gì đó khác hơn là chống mẫu xác định, hoặc là dòng mã này/thực hiện này được coi là thực hành xấu.Tại sao Unity sử dụng một Service Locator?

ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(Container)); 
+0

Tôi đã thấy điều này cũng được sử dụng rất nhiều trong Prism StockTrader RI, họ cũng sử dụng ServiceLocator với MEF. Tôi cũng bị ấn tượng vì nó là một hình mẫu chống lại, do đó tôi ngạc nhiên khi thấy nó trong một RI. Tôi tin rằng đây là việc triển khai thực hiện mẫu Locator Service giống như mô hình chống định nghĩa. – Lukazoid

+0

Bạn nhận được nó ngược: trong ví dụ của bạn, nó không phải là Unity đang sử dụng định vị dịch vụ, mà đúng hơn là mã của bạn đang hợp nhất với asp.net mvc3 thông qua trình định vị dịch vụ. Các cuộc tranh luận về mô hình Service Locator có tính chất tôn giáo. nhóm asp.net mvc đã cung cấp một cách để sử dụng DI container yêu thích của bạn và đây là cách họ đã thực hiện nó. Hãy suy nghĩ về lựa chọn thay thế. Dưới đây là một số thông tin chi tiết hơn về vấn đề http://blog.ploeh.dk/2011/08/25/ServiceLocatorRolesVsMechanics.aspx –

+0

@zespri - vì vậy không phải tất cả triển khai Unity đều sử dụng một Service Locator? –

Trả lời

0

Đó là cùng kiểu chống lại mọi người nói. Tất cả các dòng đó đang làm là thiết lập nhà cung cấp dịch vụ định vị là một cá thể của UnityServiceLocator, tức là sử dụng việc thực hiện Unity của ISerivceLocator. Tùy chọn nếu bạn muốn bạn có thể có triển khai của riêng bạn là IServiceLocator và sử dụng nó thay vì UnityServiceLocator.

Sử dụng Dịch vụ Locator được coi là một thực tế xấu vì nhiều lý do như được liệt kê here

+0

Tôi đồng ý Dịch vụ định vị là hành vi xấu, tôi chỉ không chắc chắn nếu điều này đã được sử dụng chỉ trong tên. –

+3

Nếu bạn đang sử dụng một container IOC, làm thế nào để bạn tìm thấy các container? –

+0

Nó có vị trí của nó, xem câu trả lời khác, nó giải phóng mã của bạn khỏi bị ràng buộc trực tiếp với một triển khai DI cụ thể. – Alwyn

7

Nếu bạn tạo một khuôn khổ mà được thiết kế để chứa bất khả tri định vị dịch vụ (mặc dù nó phải là một Không-Go trong một ứng dụng) là một lớp bổ sung của indirection cho phép bạn trao đổi Unity cho một cái gì đó khác nhau. Ngoài ra, việc sử dụng trình định vị dịch vụ không thực thi việc sử dụng DI cho các ứng dụng sử dụng khung công tác đó.

9

Cũ câu hỏi, nhưng vì lợi ích của người khác:

Trong khi tôi hoàn toàn đồng ý với câu thần chú "Dịch vụ Địa điểm là một mô hình chống", chắc chắn có những trường hợp ngoại lệ cho quy tắc đó.

Khi bạn sử dụng Dependency Injection (như Unity) thì, có, chắc chắn không sử dụng ServiceLocator và chỉ sử dụng phép xây dựng cho tất cả các lớp dịch vụ của bạn. (Ngoài ra, không sử dụng "mới" cho bất kỳ thứ gì ngoài các đối tượng giá trị như DTO.)

Tuy nhiên, có những trường hợp bạn không thể sử dụng chức năng tiêm xây dựng và cách duy nhất để truy cập dịch vụ là sử dụng một cách giải quyết khác để truy cập trực tiếp vào vùng chứa Unity của bạn và trong những trường hợp như vậy, ServiceLocator là một cách tiêu chuẩn tốt để thực hiện điều đó. Đây là trường hợp khi lớp đó không được bạn khởi tạo (hoặc cụ thể hơn, nó không được khởi tạo bởi Unity) mà bởi .NET framework chẳng hạn.

Một vài ví dụ đơn giản về nơi ServiceLocator có thể có ích, là để có được quyền truy cập vào các dịch vụ đăng ký tại chứa Unity của bạn từ:

  1. một thi hành một WCF IEndpointBehavior hoặc IClientMessageInspector
  2. một thi hành một WPF IValueConverter
  3. hoặc thậm chí bạn không muốn truy cập vào "dịch vụ" từ lớp học, nhưng bạn chỉ muốn viết mã có thể kiểm tra được đơn vị, nhưng vì lý do nào đó lớp học không thể được instatiated ở tất cả (hoặc không dễ dàng) vì nó thường được xây dựng bởi .NET Framework, s o bạn trích xuất mã tùy chỉnh của mình thành một lớp có thể kiểm tra và giải quyết nó trong lớp không thể kiểm tra bằng ServiceLocator.

Lưu ý rằng dòng này không phải là lý tưởng:

ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(Container)); 

Thuộc tính ServiceLocator.Current đang xảy ra để thực hiện các đại biểu được cung cấp mỗi khi bạn truy cập hiện tại, tức là một UnityServiceLocator mới sẽ được tạo ra mỗi lần .Thay vào đó, bạn có thể muốn thực hiện điều này:

IServiceLocator locator = new UnityServiceLocator(container); 
ServiceLocator.SetLocatorProvider(() => locator);