2010-04-29 10 views
5

Estoy creando una aplicación que usa AutoFac 2 para DI. He estado reading que se debe evitar utilizar un IoCHelper estático (Localizador de servicios).Evitar el localizador de servicios con AutoFac 2

IoCHelper.cs

public static class IoCHelper 
{ 
    private static AutofacDependencyResolver _resolver; 

    public static void InitializeWith(AutofacDependencyResolver resolver) 
    { 
     _resolver = resolver; 
    } 

    public static T Resolve<T>() 
    { 
     return _resolver.Resolve<T>(); 
    } 
} 

De respuestas a un previous question, he encontrado una manera de ayudar a reducir la necesidad de usar mi IoCHelper en mi UnitOfWork mediante el uso de Auto-generated Factories. Continuando por este camino, tengo curiosidad si puedo eliminar completamente mi IoCHelper.

Aquí está el panorama:

tengo una clase configuración estática que sirve como una envoltura alrededor de mi aplicación de configuración. Dado que la clase de Configuración es una dependencia de la mayoría de mis otras clases, el contenedor me impide tener que inyectar la clase de configuración en toda mi aplicación.

Settings.cs

public static class Settings 
{ 
    public static IAppSettings AppSettings 
    { 
     get 
     { 
      return IoCHelper.Resolve<IAppSettings>(); 
     } 
    } 
} 

public interface IAppSettings 
{ 
    string Setting1 { get; } 
    string Setting2 { get; } 
} 

public class AppSettings : IAppSettings 
{ 
    public string Setting1 
    { 
     get 
     { 
      return GetSettings().AppSettings["setting1"]; 
     } 
    } 

    public string Setting2 
    { 
     get 
     { 
      return GetSettings().AppSettings["setting2"]; 
     } 
    } 

    protected static IConfigurationSettings GetSettings() 
    { 
     return IoCHelper.Resolve<IConfigurationSettings>(); 
    } 
} 

¿Hay una manera de manejar esto sin necesidad de utilizar un localizador de servicio y sin tener que recurrir a la inyección de AppSettings en todas y cada clase? A continuación se enumeran las 3 áreas en las que siguen apoyándose en ServiceLocator lugar de la inyección de constructor:

  • AppSettings
  • registro
  • almacenamiento en caché

Respuesta

4

yo preferiría inyectar IAppSettings en todas las clases que lo necesita solo para mantenerlos limpios de la dependencia oculta en Settings. La pregunta es, ¿realmente necesitas rociar esa dependencia en cada clase?

Si realmente quieres ir con una clase estática de Settings, al menos intentaré que sea fácil de usar/fakeable. Considere esto:

public static class Settings 
{ 
    public static Func<IAppSettings> AppSettings { get; set; } 
} 

Y en el que construir su contenedor:

var builder = new ContainerBuilder(); 
... 
var container = builder.Build(); 

Settings.AppSettings =() => container.Resolve<IAppSettings>(); 

Esto permitiría a intercambiar con falsificaciones durante la prueba:

Settings.AppSettings =() => new Mock<IAppSettings>().Object; 

Ahora la clase AppSettings (que supongo solo hay uno de) que podría hacer con la inyección de constructor regular. Supongo también que realmente desea resolver cada llamada a sus propiedades de configuración, inyectando así un delegado de fábrica que recupera una instancia cuando sea necesario. Si esto no es necesario, debe, por supuesto, inyectar el servicio IConfigurationSettings directamente.

public class AppSettings : IAppSettings 
{ 
    private readonly Func<IConfigurationSettings> _configurationSettings; 

    public AppSettings(Func<IConfigurationSettings> configurationSettings) 
    { 
     _configurationSettings = configurationSettings; 
    } 

    public string Setting1 
    { 
     get 
     { 
      return _configurationSettings().AppSettings["setting1"]; 
     } 
    } 

    public string Setting2 
    { 
     get 
     { 
      return _configurationSettings().AppSettings["setting2"]; 
     } 
    } 
} 
+0

Ese es un buen punto. A decir verdad, probablemente no necesite inyectar esas dependencias en CADA clase, pero para los casos en que tengo la misma dependencia inyectada en una gran cantidad de clases, tenía curiosidad por saber si hay algunas mejores prácticas de DI para esto. –

+1

Ver mi respuesta actualizada. A decir verdad, me he visto obligado a hacer esto en una ocasión: cuando la inyección del constructor no se podía usar (el diseñador necesitaba un constructor sin parámetros). –

+0

Bonita solución – Baldy

Cuestiones relacionadas