Come utilizzo StructureMap con tipi generici non chiusi utilizzando Scan con un costruttore “greedy”

Tra le varie domande e post sui blog di Stack Overflow vi è una quantità ragionevole di documentazione sull’argomento dei generici aperti e di StructureMap. Sfortunatamente, mi manca qualcosa mentre i miei tentativi di usare la scan per eseguire la configurazione insieme a un’implementazione di class con un costruttore “avido” hanno ancora funzionato.

Voglio StructureMap per afferrare un’istanza della class sottostante tramite i riferimenti alla sua interfaccia implementata. ToCsvService esiste in un assembly non referenziato denominato Infrastruttura. IToCsvService esiste in un assembly di riferimento denominato Core. Come puoi vedere, ToCsvService ha un costruttore “avido”.

 public class ToCsvService : IToCsvService { public ToCsvService(ICollection collection) { } } 

Ho lasciato a StructureMap la conoscenza di ToCsvService tramite il metodo ConnectImplementationsToTypesClosing .

 ObjectFactory.Initialize(cfg => { cfg.Scan(scan => { scan.Assembly("Infrastructure"); scan.WithDefaultConventions(); // even with this call StructureMap cannot use ToCsvService // instance of IToCsvService (though wouldn't expect it to) scan.ConnectImplementationsToTypesClosing (typeof(IToCsvService)); }); }); 

Dal metodo ObjectFactory.WhatDoIHave() appare che StructureMap è a conoscenza di ToCsvService .

 PluginType Nome Descrizione                                                                                                                          
 -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------------------------------
 IToCsvService`1 (IToCsvService`1)                                                                                                                                                                                                                                      
 Scoperto come: Transitorio                                                                                                                                                                                                                                                                                  
                                       6202a7ee-89a4-4edd-831d-4867b7dd1a7e Istanza configurata di Infrastructure.Services.ToCsvService`1, Infrastruttura, Versione = 1.0.0.0, Cultura = neutra, PublicKeyToken = null 
                                       Infrastructure.Services.ToCsvService`1, Infrastructure, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null Istanza configurata di Infrastructure.Services.ToCsvService`1, Infrastruttura, Versione = 1.0.0.0, Culture = neutral, PublicKeyToken = null                   

Tuttavia, quando IToCsvService in un costruttore di Controller, lancia l’eccezione

StructureMap Exception Code: 202 Nessuna istanza predefinita definita per PluginFamily Core.Services.IToCsvService`1 [[UI.Models.MachineForm, UI, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null]], Core, Versione = 1.0. 0.0, Culture = neutral, PublicKeyToken = null

Immagino che questo sia dovuto al fatto che StructureMap non ha idea di cosa consegnare il costruttore “greedy” di ToCsvService . C’è qualche modo per rendere StructureMap in grado di giocare bene con questo costruttore? Devo passare da un costruttore e semplicemente impostare la proprietà della raccolta dopo l’istanziazione?

La domanda Structuremap e i dettagli dei tipi generici in qualche modo sto cercando di fare ma non utilizza una scansione per farlo. La risposta fornita da Joshua Flanagan utilizza la configurazione For(x).Use(y) , che potrebbe funzionare se non eseguissi la scansione dell’assembly perché non ho un ToCsvService riferimento.

modificare

Volevo vedere se l’utilizzo di un meccanismo diverso per consentire a StructureMap di identificare le istanze di ToCsvService avrebbe avuto un effetto. Cambia ciò che viene segnalato in ObjectFactory.WhatDoIHave() e genera un’eccezione diversa. Ecco un esempio dell’utilizzo di AddAllTypesOf .

 ObjectFactory.Initialize(cfg => { cfg.Scan(scan => { scan.Assembly("Infrastructure"); scan.WithDefaultConventions(); scan.AddAllTypesOf(typeof(IToCsvService)); }); }); 

Dopo aver utilizzato il precedente dump da ObjectFactory.WhatDoIHave() è

 PluginType Nome Descrizione                                                                                                                                            
 -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------------------
 IToCsvService`1 (IToCsvService`1) Infrastructure.Services.ToCsvService`1, Infrastruttura, Versione = 1.0.0.0, Culture = neutral, PublicKeyToken = null Istanza configurata di Infrastructure.Services.ToCsvService`1, Infrastruttura, Versione = 1.0.0.0, Cultura = neutrale, PublicKeyToken = null                   
 Scoperto come: Transitorio

                                      Infrastructure.Services.ToCsvService`1, Infrastructure, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null Istanza configurata di Infrastructure.Services.ToCsvService`1, Infrastruttura, Versione = 1.0.0.0, Culture = neutral, PublicKeyToken = null                   
 -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------------------
 IToCsvService`1 (IToCsvService`1) Infrastructure.Services.ToCsvService`1, Infrastruttura, Versione = 1.0.0.0, Culture = neutral, PublicKeyToken = null Istanza configurata di Infrastructure.Services.ToCsvService`1, Infrastruttura, Versione = 1.0.0.0, Cultura = neutrale, PublicKeyToken = null                   
 Scoperto come: Transitorio

                                      Infrastructure.Services.ToCsvService`1, Infrastructure, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null Istanza configurata di Infrastructure.Services.ToCsvService`1, Infrastruttura, Versione = 1.0.0.0, Culture = neutral, PublicKeyToken = null

Con questa configurazione lancio questa eccezione:

StructureMap Exception Code: 202 Nessuna istanza predefinita definita per PluginFamily System.Collections.Generic.ICollection`1 [[UI.Models.MachineForm, UI, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null]], mscorlib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089

Per me l’eccezione indica che StructureMap sa di aver bisogno di ICollection per istanziare ToCsvService ma non sa da dove arrivare. Il che va al commento di Jimmy dal basso sull’utilizzo di StructureMap e dell’Input del costruttore . Tuttavia, ciò non sembra ansible senza aggiungere un riferimento esplicito all’assembly Infrastruttura.

Domande su Stack Overflow un po ‘correlate su StructureMap e Generics

  • Structuremap e tipi generici
  • Iniezione Structure settap in tipo generico aperto?
  • StructureMap Registrazione automatica per tipi generici usando Scan

Post sui blog relativi a StructureMap e Generics

  • Advanced StructureMap: connettere le implementazioni per aprire tipi generici
  • Advanced StructureMap: convenzioni di registrazione personalizzate per tipi parzialmente chiusi
  • Apri tipi generici in StructureMap