2012-02-03 14 views
5

He visto esta línea de código en varios tutoriales para usar Unity en asp.net mvc3. Tenía la impresión de que Service Locator es un antipatrón y no una buena práctica. ¿Este Localizador de servicios es algo más que el antipatrón definido o esta línea de código/esta implementación se considera una mala práctica?¿Por qué Unity usa un Localizador de servicios?

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

He visto esto usado demasiado, en el Prism StockTrader RI, también usan el ServiceLocator con MEF. También tuve la impresión de que era un antipatrón, por lo que me sorprende verlo en un RI. Creo que esta es la misma implementación del patrón Localizador de servicio que el anti-patrón definido. – Lukazoid

+0

Lo consiguió al revés: en su ejemplo, no es Unity el que está utilizando el localizador de servicios, sino que su código está conectado a asp.net mvc3 a través del localizador de servicios. Los debates sobre el patrón de Localizador de servicios son de naturaleza religiosa. El equipo asp.net mvc tuvo que proporcionar una forma de usar su contenedor DI favorito y esta es la forma en que lo implementaron. Piensa en alternativas. Aquí hay más información sobre el problema http://blog.ploeh.dk/2011/08/25/ServiceLocatorRolesVsMechanics.aspx –

+0

@zespri - ¿entonces no todas las implementaciones de Unity usan un Localizador de servicios? –

Respuesta

0

Es el mismo anti-Patten que habla la gente. Lo único que hace esa línea es establecer que el proveedor del localizador de servicios sea una instancia de UnityServiceLocator, es decir, que use la implementación de Unity del ISerivceLocator. Opcionalmente, si desea que pueda tener su propia implementación, es IServiceLocator y use eso en lugar de UnityServiceLocator.

el uso de servicios de localización se considera una mala práctica por varias razones que se enumeran here

+0

Acepto que el Localizador de servicios es una mala práctica, simplemente no estaba seguro de si se usaba solo con el nombre. –

+3

Si está utilizando un contenedor IOC, ¿cómo se encuentra el contenedor? –

+0

Tiene su lugar, ver la otra respuesta, libera su código de estar directamente vinculado a una implementación particular de DI. – Alwyn

7

Si crea un marco que está diseñado para ser recipiente agnóstica el localizador de servicios (aunque debe ser un no-go en una aplicación) es una capa adicional de direccionamiento indirecto que le permite cambiar Unity por algo diferente. Además, el uso del localizador de servicios no exige el uso de DI para las aplicaciones que usan ese marco.

9

vieja pregunta, pero para el beneficio de los demás:

Si bien estoy totalmente de acuerdo con el mantra "servicio de localización es un anti-patrón", definitivamente hay excepciones a esta regla.

Cuando utiliza Dependency Injection (como Unity) entonces, sí, ciertamente no usa ServiceLocator y solo usa la inyección de constructor para todas sus clases de servicio. (Tampoco utilice "nuevo" para nada que no sea objetos de valor como DTO).

Sin embargo, hay casos donde simplemente no puede usar la inyección de constructor y entonces la única forma de obtener acceso a un servicio es utilice una solución alternativa para acceder directamente a su contenedor de Unity, y en tales casos, ServiceLocator es una buena forma estándar para lograrlo. Este es el caso cuando la clase no es instanciada por usted (o más específicamente, no está instanciada por Unity), sino por .NET Framework, por ejemplo.

Algunos ejemplos simples de donde ServiceLocator podría ser útil, es conseguir el acceso a los servicios registrados en el contenedor de la Unidad de:

  1. una implementación de un WCF IEndpointBehavior o IClientMessageInspector
  2. una implementación de un WPF IValueConverter
  3. o puede que no necesariamente quiera acceder a los "servicios" de la clase, pero simplemente desea escribir un código que pueda ser comprobado por la unidad, pero por alguna razón la clase no puede instalarse (o no fácil) porque normalmente sería construido por .NET Framework, s o extraes tu código personalizado en una clase que es comprobable y lo resuelves en la clase no comprobable usando ServiceLocator.

Tenga en cuenta que esta línea no es lo ideal:

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

La propiedad ServiceLocator.Current se va a ejecutar el delegado proporciona cada vez que acceda actual, es decir, un nuevo UnityServiceLocator se va a poner cada vez creado .En su lugar, probablemente desee hacer esto:

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