2016-07-14 1 views
1

Je tente de construire une application modulaire en utilisant MEF.
Cependant, lors de la composition, il semble ignorer SetExportedValue(..., ...), ce qui fait qu'il ne trouve pas les valeurs/objets dont j'ai besoin.Pourquoi MEF échoue-t-il sur le constructeur de la pièce?

Voici mon (anonymisées et simplifié) Code:

interface IPlugin { } 

class MyClass 
{ 
    [ImportsMany(typeof(IPlugin))] 
    public IEnumerable<Lazy<IPlugin>> Plugins; 

    public LoadParts() 
    { 
     var ac = new AggregateCatalog(); 
     ac.Catalogs.Add(new AssemblyCatalog(typeof(PluginManager).Assembly)); 

     // imagine adding some DirectoryCatalogs here 

     var cc = new CompositionContainer(ac); 
     cc.ComposeExportedValue("MyValue", someinstance); 
     cc.ComposeParts(this); 
    } 
} 

[Export(typeof(IPlugin))] 
class MyPart : IPlugin 
{ 
    [ImportingConstructor] 
    public MyPart([Import("MyValue")] sometype arg) 
    { } 
} 

Il en résulte dans le message d'erreur suivant:

System.ComponentMode l.Composition Avertissement: 1: La ComposablePartDefinition 'MyNamespace.MyPart' a été rejetée. La composition reste inchangée. Les modifications ont été rejetées en raison des erreurs suivantes: La composition a produit une erreur de composition unique. La cause première est fournie ci-dessous. Consultez la propriété CompositionException.Errors pour plus d'informations.

1) Aucune exportation n'a été trouvé qui correspondent à la contrainte:

ContractName MyValue 
RequiredTypeIdentity somenamespace.sometype 

Entraînant: Impossible de définir l'importation « MyNamespace.MyPart..ctor (paramètre = » ... "ContractName =" ... ")" sur la partie "MyNamespace.MyPart".
élément: MyNamespace.MyPart..ctor (paramètre = "... " ContractName =" ... ") -> MyNamespace.MyPart -> DirectoryCatalog (Path =" ./")

Est-ce que je me méprends sur le fonctionnement des constructeurs de pièces?
Comment l'obtenir pour accepter le paramètre constructeur?


Modifier pour claification: someinstance est une instance spécifique de sometype. Je ne veux pas ajouter un type au conteneur, mais une instance de classe spécifique.

Répondre

1

Votre ImportingConstructor a également besoin de contrats valides, et pas seulement de valeurs.

Ceci est un exemple, comment mon constructeur fonctionne:

[ImportingConstructor] 
    public MyType([Import] IStatus status, [Import] IProtocoll protocoll) { 
    } 

Comme vous pouvez le voir, vous avez besoin d'utiliser des interfaces comme contructor-paramètres.

Ces interfaces sont simples et sans aucun attribut requis.

Snippet de IProtocoll

public interface IProtocoll { 

    IProtocollStateController ProtocollController { get; set; } 

    void WriteProtocoll(string action, string message, bool? result, Guid conditionId); 

    void WriteProtocoll(Protocoll protocoll); 

    List<Protocoll> GetAllProtocoll(); 
    } 

Je vous suggère de transformer votre MyValue dans une interface valide. Cela peut être un peu exagéré pour une chaîne simple mais c'est le fonctionnement de MEF.

Acclamations

+0

'" MyValue "' contient une instance de classe spécifique, cependant. Si je ne fais que '[Exporter]' cette classe, cela générera une nouvelle instance sur la composition que je ne veux pas, non? –

+0

Cela dépend de la façon dont vous le faites. [This] (https://stefanhenneken.wordpress.com/2011/08/30/mef-teil-6-constructor-injection/) est en allemand, mais le code est en anglais et montre comment c'est fait. Vous pouvez en outre faire de votre contructor-paramètre un Singleton afin que vous n'ayez pas d'autres instances – lokusking