Registre los tipos genéricos abiertos para todos los tipos que implementan alguna interfaz con StructureMap

StackOverflow https://stackoverflow.com/questions/6814961

  •  25-10-2019
  •  | 
  •  

Pregunta

Quiero registrar todos mis tipos implementando IManager para que puedan usarse como el tipo T para el genérico Lazy<T> clase.

Por ejemplo:

public TetraRadioPropertyUpdater(Lazy<IRadioManager> lazyRadioManager)

Utilizo un escáner hecho a sí mismo porque mis tipos e interfaces de concreto son internos y, por lo tanto, no puedo usar el mecanismo de escaneo StructureMap incorporado.

En la primera declaración del registro de bucle todo mi IManager tipos como For<IRadioManager>().Singleton().Use<RadioManager>()

Además, quiero que se registren para que puedan usarse como el tipo genérico para Lazy<T> me gusta For<Lazy<IRadioManager>().Use<Lazy<RadioManger>>()

 InterfaceScanner<IManager> interfaceScanner = new InterfaceScanner<IManager>();

 // managerMapping looks like:
 // { IRadioManager, RadioManager }
 // { ICallManager, CallManager }
 // .. more manager interface to plugin type pairs  
 foreach (KeyValuePair<Type, Type> managerMapping in interfaceScanner.Process())
 {
    // the key is the plugin type, value is the concrete type
    For(managerMapping.Key).Singleton().Use(managerMapping.Value);

    // something like this.. ?
    For(typeof(Lazy<>)).Singleton().Use(c => new Lazy(() => c.GetInstance(managerMapping.Value)));
 }

es posible? ¿Cómo necesito configurarlo para StructureMap?

¿Fue útil?

Solución

ACTUALIZAR: StructureMap V3 implementa esto de la caja, por lo que este truco ya no es necesario.


Puede registrar explícitamente las clases como esta:

container = new Container(x =>
{
    x.Scan(y =>
    {
        y.TheCallingAssembly();
        y.WithDefaultConventions();
    });

    x.For<Lazy<IFoo>>().Use(y => new Lazy<IFoo>(y.GetInstance<Foo>));
    x.For<Lazy<IBar>>().Use(y => new Lazy<IBar>(y.GetInstance<Bar>));
    x.For<Lazy<IBaz>>().Use(y => new Lazy<IBaz>(y.GetInstance<Baz>));
});

Sin embargo, sería mejor si esto se hiciera automáticamente. Idealmente, la siguiente sintaxis sería buena.

x.For(typeof(Lazy<>)).Use(typeof(Lazy<>));

Desafortunadamente, en tiempo de ejecución, StructureMap intentará encontrar el constructor "más codicioso" para Lazy<T> y conformarse con public Lazy(Func<T> valueFactory, bool isThreadSafe). Ya que no sabe qué hacer con el parámetro booleano istreadsafe. Lanzará una excepción. Puedes explícitamente decir StructureMap qué valor usar como este.

x.For(typeof(Lazy<>)).Use(typeof(Lazy<>))
 .CtorDependency<bool>("isThreadSafe").Is(true);

Que detendrá las excepciones y usará el valor de "verdadero" para el parámetro IstreadSafe. La documentación para los estados perezosos de que el modo de seguridad del hilo del valor predeterminado Lazy(Func<T> valueFactory) El constructor es LazyThreadSafetyMode.ExecutionAndPublication, que también es lo que obtienes al pasar verdadero al parámetro istreadsafe del constructor anterior, por lo que obtendremos el mismo comportamiento que si llamáramos al constructor que realmente queríamos usar en primer lugar (por ejemplo, Lazy(Func<T> valueFactory)). Puedes leer sobre la clase perezosa con más detalle aquí.

Me doy cuenta de que esto no responde directamente a su pregunta con respecto a la clase de escáner personalizada, pero debería darle un buen comienzo, espero.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top