2012-06-11 5 views
5

Ich verstehe MEF nicht sehr gut, also hoffentlich ist dies eine einfache Lösung, wie ich denke, es funktioniert.MEF GetExports <T, TMetaDataView> nichts zurückgeben mit AllowMultiple = True

Ich versuche MEF zu verwenden, um einige Informationen über eine Klasse und wie es verwendet werden soll. Ich verwende die Metadaten-Optionen, um dies zu erreichen. Meine Schnittstellen und Attribut sieht wie folgt aus:

public interface IMyInterface 
{ 
} 

public interface IMyInterfaceInfo 
{ 
    Type SomeProperty1 { get; } 
    double SomeProperty2 { get; } 
    string SomeProperty3 { get; } 
} 

[MetadataAttribute] 
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] 
public class ExportMyInterfaceAttribute : ExportAttribute, IMyInterfaceInfo 
{ 
    public ExportMyInterfaceAttribute(Type someProperty1, double someProperty2, string someProperty3) 
     : base(typeof(IMyInterface)) 
    { 
     SomeProperty1 = someProperty1; 
     SomeProperty2 = someProperty2; 
     SomeProperty3 = someProperty3; 
    } 

    public Type SomeProperty1 { get; set; } 
    public double SomeProperty2 { get; set; } 
    public string SomeProperty3 { get; set; } 
} 

Die Klasse, die mit dem Attribut dekoriert ist wie folgt aussieht:

[ExportMyInterface(typeof(string), 0.1, "whoo data!")] 
[ExportMyInterface(typeof(int), 0.4, "asdfasdf!!")] 
public class DecoratedClass : IMyInterface 
{ 
} 

Die Methode, um den Import zu verwenden versucht, sieht wie folgt aus:

private void SomeFunction() 
{ 
    // CompositionContainer is an instance of CompositionContainer 
    var myExports = CompositionContainer.GetExports<IMyInterface, IMyInterfaceInfo>(); 
} 

In meinem Fall myExports ist immer leer. In meinem CompositionContainer habe ich einen Part in meinem Katalog, der zwei ExportDefinitions hat, beide mit den folgenden ContractName: "MyNamespace.IMyInterface". Die Metadata wird auch korrekt per meine Exporte geladen.

Wenn ich die AllowMultiple Setter entfernen und nur ein exportierten Attribut enthalten, hat die myExports Variable jetzt den einzelnen Export mit seinen geladenen Metadaten.

Was mache ich falsch?

EDIT: Wenn ich schwach Metadaten verwenden eingegeben haben, ist meine Export plötzlich zufrieden:

var myExports = CompositionContainer.GetExports<IMyInterface, IDictionary<string, object>>(); 

Irgendwelche Ideen, warum?

Antwort

9

Es ist bekannt, dass MEF einige Probleme im Umgang mit AllowMultiple = true hat. Für eine vollständige Erklärung könnten Sie zum Beispiel here aussehen, jedenfalls ergibt es sich aus der Tatsache, dass die Metadaten in einem Dictionary gespeichert werden, wo die Werte Arrays sind, wenn AllowMultiple wahr ist, und so etwas kann nicht auf Ihre IMyInterfaceInfo zugeordnet werden.

Dies ist die Problemumgehung, die ich verwende. Zunächst sollte das Attribut von Attribut ableiten, nicht aus ExportAttribute:

[MetadataAttribute] 
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] 
public class ExportMyInterfaceAttribute : Attribute, IMyInterfaceInfo 
{ 
    public ExportMyInterfaceAttribute(Type someProperty1, double someProperty2, string someProperty3) 

    { 
     SomeProperty1 = someProperty1; 
     SomeProperty2 = someProperty2; 
     SomeProperty3 = someProperty3; 
    } 

    public Type SomeProperty1 { get; set; } 
    public double SomeProperty2 { get; set; } 
    public string SomeProperty3 { get; set; } 
} 

Dies bedeutet, dass die exportierte Klasse 3 Attribute, ein Standard-Export und Ihre benutzerdefinierte Attribute haben sollte:

[Export(typeof(IMyInterface))] 
[ExportMyInterface(typeof(string), 0.1, "whoo data!")] 
[ExportMyInterface(typeof(int), 0.4, "asdfasdf!!")] 
public class DecoratedClass : IMyInterface 

Dann haben Sie um eine Ansicht für die Metadaten zu definieren, die importiert werden. Dies muss einen Konstruktor haben, der das IDictionary als Parameter akzeptiert. Etwas wie folgt aus:

public class MyInterfaceInfoView 
{ 
    public IMyInterfaceInfo[] Infos { get; set; } 

    public MyInterfaceInfoView(IDictionary<string, object> aDict) 
    { 
     Type[] p1 = aDict["SomeProperty1"] as Type[]; 
     double[] p2 = aDict["SomeProperty2"] as double[]; 
     string[] p3 = aDict["SomeProperty3"] as string[]; 

     Infos = new ExportMyInterfaceAttribute[p1.Length]; 
     for (int i = 0; i < Infos.Length; i++) 
      Infos[i] = new ExportMyInterfaceAttribute(p1[i], p2[i], p3[i]); 
    } 
} 

Jetzt sollten Sie in der Lage sein, erfolgreich

var myExports = CompositionContainer.GetExports<IMyInterface, MyInterfaceInfoView>(); 
+0

Yep zu nennen, das ist, was ich am Ende tun, nach dem folgenden Artikel zu lesen: http://blogs.microsoft.co. il/blogs/bnaya/archive/2010/01/29/mef-fuer-anfänger-wiederholbare-metadaten-part-9.aspx Ich wollte dies gestern posten, wurde aber in andere Sachen gezogen, bevor ich fertig war, also genieße deine Punkte ! – sohum

+0

Es ist nicht notwendig, die Klasse von "Attribut" anstelle von "ExportAttribute" zu erben. Der Punkt von 'MetadataAttributeAttribute' ist kurz und knapp ;-).Die Verwendung einer benutzerdefinierten Metadatenansicht und das manuelle Behandeln der Arrays funktioniert für mich. Es ist nicht offensichtlich aus der Dokumentation, dass "AllowMultiple" dazu führt, dass Metadateneinträge zu Arrays werden, so komisch ... – binki