2012-06-11 11 views
5

Nie rozumiem MEF bardzo dobrze, więc mam nadzieję, że jest to prosta poprawka, jak myślę, że to działa.MEF GetExports <T, TMetaDataView> nic nie zwracając z AllowMultiple = True

Próbuję użyć MEF, aby uzyskać informacje o klasie i sposobie jej użycia. Używam opcji Metadane, aby spróbować to osiągnąć. Moi interfejsy i atrybut wygląda następująco:

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

Klasa, która jest ozdobiona atrybutu wygląda następująco:

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

Metoda, która stara się wykorzystać import wygląda następująco:

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

W moim przypadku myExports jest zawsze pusty. W moim CompositionContainer, mam część w moim katalogu, która ma dwa ExportDefinitions, oba z następującym ContractName: "MyNamespace.IMyInterface". Numer Metadata jest również poprawnie wczytywany do mojego eksportu.

Po usunięciu settera AllowMultiple i uwzględnieniu tylko jednego eksportowanego atrybutu zmienna myExports ma teraz pojedynczy eksport z załadowanymi metadanymi.

Co robię źle?

EDIT: Jeśli użyję słabo wpisane Metadane, mój eksport jest nagle spełnione:

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

Jakieś pomysły dlaczego?

Odpowiedz

9

Wiadomo, że MEF ma pewne problemy podczas pracy z AllowMultiple = true. Aby uzyskać pełne wyjaśnienie, możesz na przykład wyglądać here, tak czy inaczej wynika to z faktu, że metadane są zapisywane w Słowniku, gdzie wartości są tablicami, gdy AllowMultiple ma wartość true, a takiej rzeczy nie można zmapować na Twojej IMyInterfaceInfo.

Jest to obejście, którego używam. Przede wszystkim Twój atrybut powinien czerpać z atrybutów, a nie z 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; } 
} 

Oznacza to, że eksportowane klasa powinna mieć 3 atrybuty standardowy eksport i niestandardowe atrybuty:

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

Wtedy masz aby zdefiniować widok dla metadanych, które zostaną zaimportowane. Musi to być konstruktor, który pobiera parametr IDictionary jako parametr. Coś takiego:

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

Teraz powinieneś być w stanie z powodzeniem nazwać

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

Tak, to, co skończyło się robi, po przeczytaniu następujący artykuł: http://blogs.microsoft.co. il/blogs/bnaya/archiwum/2010/01/29/mef-for-beginner-repeatable-metadata-part-9.aspx Miałem zamiar opublikować to wczoraj, ale zostałem wciągnięty w inne rzeczy, zanim mogłem dokończyć, więc ciesz się z twoich punktów ! – sohum

+0

Nie ma potrzeby, aby klasa dziedziczyła z "Atrybutu" zamiast "Eksportuj atrybut". Celem 'MetadataAttributeAttribute' jest zwięzłość i precyzja ;-).Używanie niestandardowego widoku metadanych i ręczne radzenie sobie z tablicami działa dla mnie. Z dokumentacji nie wynika, że ​​'AllowMultiple' powoduje, że wpisy metadanych stają się tablicami, więc dziwne ... – binki

Powiązane problemy