Enregistrez-types génériques ouverts pour tous les types d'application une interface avec StructureMap

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

  •  25-10-2019
  •  | 
  •  

Question

Je veux enregistrer tous mes types d'application IManager afin qu'ils puissent être utilisés comme type T pour la classe Lazy<T> générique.

Par exemple:

public TetraRadioPropertyUpdater(Lazy<IRadioManager> lazyRadioManager)

J'utilise un scanner auto fait parce que mes types de béton et les interfaces sont internes et à cet effet, je ne peux pas utiliser le haut dans StructureMap mécanisme de balayage.

Dans la première déclaration de la boucle enregistrer tous mes types de IManager comme For<IRadioManager>().Singleton().Use<RadioManager>()

En plus, je veux qu'ils soient enregistrés afin qu'ils puissent être utilisés comme type générique pour Lazy<T> comme 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)));
 }

Est-ce possible? Comment dois-je configurer pour StructureMap?

Était-ce utile?

La solution

Mise à jour: StructureMap v3 implémente cette sortie de la boîte,

cette astuce n'est plus nécessaire.

Vous pouvez enregistrer explicitement les classes comme ceci:

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

Il serait plus agréable si cela était fait automatiquement, cependant. Idéalement, la syntaxe suivante serait bien.

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

Malheureusement, lors de l'exécution, StructureMap tentera de trouver le constructeur « vorace » pour Lazy<T> et Settle sur public Lazy(Func<T> valueFactory, bool isThreadSafe). Comme il ne sait pas quoi faire avec le paramètre isThreadSafe booléen. Il lancera une exception. Vous pouvez explicitement tell StructureMap valeur à utiliser comme celui-ci.

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

Ce qui arrêtera les exceptions, et utiliser la valeur « true » pour le paramètre isThreadSafe. La documentation de Lazy indique que le mode de sécurité de fil du constructeur de Lazy(Func<T> valueFactory) par défaut est LazyThreadSafetyMode.ExecutionAndPublication, qui est aussi ce que vous obtenez en passant vrai dans le paramètre isThreadSafe du constructeur ci-dessus, donc nous allons obtenir le même comportement que si nous avons appelé le constructeur nous voulions réellement utiliser en premier lieu (par exemple Lazy(Func<T> valueFactory)). Vous pouvez lire la classe Lazy plus en détail .

Je me rends compte que cela ne répond pas directement à votre question en ce qui concerne la classe du scanner personnalisé, mais il devrait vous donner un bon départ, je l'espère.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top