Registrati tipi generici aperti per tutti i tipi di applicazione alcune interfaccia con StructureMap

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

  •  25-10-2019
  •  | 
  •  

Domanda

Vorrei iscrivermi tutti i miei tipi di applicazione IManager in modo che possano essere utilizzati come tipo di T per la classe Lazy<T> generica.

Ad esempio:

public TetraRadioPropertyUpdater(Lazy<IRadioManager> lazyRadioManager)

Io uso uno scanner self made perché i miei tipi e le interfacce di cemento sono interni e per questo non posso utilizzare il costruito nel StructureMap meccanismo di scansione.

Nella prima istruzione del ciclo registrare tutti i miei tipi IManager come For<IRadioManager>().Singleton().Use<RadioManager>()

Come pure, voglio che essere registrati in modo che possano essere utilizzati come il tipo generico per Lazy<T> come 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)));
 }

È possibile? Come devo configurarlo per StructureMap?

È stato utile?

Soluzione

UPDATE:. StructureMap v3 implementa questa fuori dalla scatola, quindi questo trucco non è più necessario


È possibile registrare in modo esplicito le classi in questo modo:

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>));
});

Sarebbe bello se questo fosse fatto automaticamente, però. Idealmente, la seguente sintassi sarebbe bello.

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

Purtroppo, in fase di esecuzione, StructureMap tenterà di trovare il costruttore "golosi" per Lazy<T> e stabilirsi su public Lazy(Func<T> valueFactory, bool isThreadSafe). Dal momento che non sa cosa fare con il parametro booleano isThreadSafe. Sarà un'eccezione. È possibile in modo esplicito dire StructureMap quale valore per l'uso come questo.

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

che si fermerà le eccezioni, e utilizzare il valore "true" per il parametro isThreadSafe. La documentazione per pigro afferma che la modalità di sicurezza filo del costruttore di default Lazy(Func<T> valueFactory) è LazyThreadSafetyMode.ExecutionAndPublication, che è anche quello che si ottiene passando vero nel parametro isThreadSafe del costruttore sopra, così avremo lo stesso comportamento, come se abbiamo chiamato il costruttore in realtà abbiamo voluto utilizzare in primo luogo (ad es Lazy(Func<T> valueFactory)). Si può leggere sulla classe pigro in modo più dettagliato qui .

Mi rendo conto che questo non risponde direttamente alla tua domanda per quanto riguarda la classe dello scanner personalizzato, ma dovrebbe darvi una buona partenza, mi auguro.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top