37 votes

Comment utiliser StructureMap avec des types génériques non fermés à l'aide de Scan avec un constructeur "glouton"

Entre les différents Débordement de Pile questions et des billets de blog, il est assez raisonnable de documentation sur le sujet de l'open de génériques et de StructureMap. Malheureusement, je dois être en manque de quelque chose que mes tentatives à l'aide d' scan pour effectuer la configuration avec une classe de mise en œuvre est un "gourmand" constructeur ont encore du travail.

Je veux StructureMap de saisir une instance de la classe via des références à son œuvre de l'interface. ToCsvService existe en une non référencé à l'assemblée a appelé l'Infrastructure. IToCsvService existe dans un assembly référencé appelé Noyau. Comme vous pouvez le voir ToCsvService a un "gourmand" du constructeur.

public class ToCsvService<TSource> : IToCsvService<TSource>
{
    public ToCsvService(ICollection<TSource> collection)
    {
    }
}

Je laisse StructureMap savoir sur ToCsvService via l' ConnectImplementationsToTypesClosing méthode.

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

De la ObjectFactory.WhatDoIHave() méthode, il apparaît que StructureMap est conscient de l' ToCsvService.

Typeplugin Nom Description 
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IToCsvService`1 (IToCsvService`1) 
L'étendue ainsi: Transitoire 
 6202a7ee-89a4-4edd-831d-4867b7dd1a7e Configuré Instance de l'Infrastructure.Services.ToCsvService`1, de l'Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 
 L'Infrastructure.Services.ToCsvService`1, de l'Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null Configuré Instance de l'Infrastructure.Services.ToCsvService`1, de l'Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 

Cependant, quand je spécifier IToCsvService<CustomerViewModel> dans un Contrôleur constructeur qu'il lève l'exception

StructureMap Code D'Exception: 202 Aucune Instance par Défaut définie pour PluginFamily de Base.Services.IToCsvService`1[[INTERFACE utilisateur.Modèles.MachineForm, INTERFACE utilisateur, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

J'imagine que c'est parce que StructureMap a aucune idée de ce à part, les "gourmands" ToCsvService constructeur. Est-il d'une certaine manière que je peux faire de StructureMap en mesure de jouer gentil avec ce constructeur? Dois-je changer à partir d'un constructeur et il suffit de régler la collection de la propriété après l'instanciation?

La question de Structuremap et les types génériques de détails un peu je suis en train de faire, mais ne pas utiliser un scanner de le faire. La réponse fournie par Joshua Flanagan utilise l' For(x).Use(y) configuration, qui pourrait fonctionner si je n'étais pas la numérisation de l'assemblée parce que je n'ai pas de référence ToCsvService.

Modifier

Je voulais voir si à l'aide d'un mécanisme différent pour laisser StructureMap à identifier les cas d' ToCsvService<> aurait un effet. Elle change ce qui est rapporté en ObjectFactory.WhatDoIHave() et jette une autre exception. Voici un exemple d'utilisation de AddAllTypesOf.

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

        scan.AddAllTypesOf(typeof(IToCsvService<>));
    });
});

Après l'utilisation de la au-dessus de l'image d' ObjectFactory.WhatDoIHave() est

Typeplugin Nom Description 
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IToCsvService`1 (IToCsvService`1) De L'Infrastructure.Services.ToCsvService`1, de l'Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null Configuré Instance de l'Infrastructure.Services.ToCsvService`1, de l'Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 
L'étendue ainsi: Transitoire

 L'Infrastructure.Services.ToCsvService`1, de l'Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null Configuré Instance de l'Infrastructure.Services.ToCsvService`1, de l'Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IToCsvService`1 (IToCsvService`1) De L'Infrastructure.Services.ToCsvService`1, de l'Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null Configuré Instance de l'Infrastructure.Services.ToCsvService`1, de l'Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 
L'étendue ainsi: Transitoire

 L'Infrastructure.Services.ToCsvService`1, de l'Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null Configuré Instance de l'Infrastructure.Services.ToCsvService`1, de l'Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

Avec cette configuration, je jette cette exception:

StructureMap Code D'Exception: 202 Aucune Instance par Défaut définie pour PluginFamily Système.Les Collections.Génériques.ICollection`1[[INTERFACE utilisateur.Modèles.MachineForm, INTERFACE utilisateur, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

Pour moi l'exception indique que StructureMap sait qu'il a besoin d'un ICollection<MachineForm> d'instancier ToCsvService , mais ne savez pas par où obtenir à partir de. Qui va à Jimmy de commentaire ci-dessous sur l'utilisation de StructureMap et Constructeur injection par mutateur. Cependant, cela ne semble pas possible sans l'ajout d'une référence explicite à l'Infrastructure de l'assemblée.

En quelque sorte liée Débordement de Pile questions sur StructureMap & Génériques

Les Blogs posts concernant StructureMap & Génériques

10voto

Jimmy Bogard Points 8294

Existe-t-il des implémentations concrètes de IToCsvService? Ou simplement le type ouvert ToCsvService?

ConnectImplementationsToTypesClosing sert à connecter quelque chose comme un CustomerViewModelToCsvService concret à IToCsvService <>. Si vous souhaitez connecter des classes ouvertes à des interfaces ouvertes, vous avez besoin des éléments suivants:

 For(typeof(IToCsvService<>)).Use(typeof(ToCsvService<>));
 

Ici, je connecte le type d'interface ouverte au type de classe ouvert.

0voto

Xenophile Points 676

En fait, dans la version actuelle, cela devrait être très simple. Tout ce que vous avez à faire est de fournir l'argument lorsque vous appelez pour obtenir une nouvelle instance de l'objet. Pour ce faire, vous utilisez la méthode "With" sur objectfactory.

Cela vous permet d'utiliser le constructeur glouton. Cependant, cela signifie également que vous devez savoir que vous avez besoin de la collection dans cet exemple. Donc, ce n'est pas la méthode optimale d'injection d'état.

 var newObject = ObjectFactory.With<ICollection<CustomerViewModel>>(SomeCollection)
                .GetInstance<IToCsvService<CustomerViewModel>>();
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X