6

私は MEF をよく理解していないので、うまくいけば、これがどのように機能すると思うかを簡単に修正できます。

MEF を使用して、クラスとその使用方法に関する情報を取得しようとしています。これを実現するために、メタデータ オプションを使用しています。私のインターフェイスと属性は次のようになります。

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

属性で装飾されたクラスは次のようになります。

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

インポートを使用しようとしているメソッドは次のようになります。

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

私の場合myExportsは常に空です。私の CompositionContainer には、私のカタログに 2 つの パーツ がありExportDefinitions、両方とも次のものがありますContractName: "MyNamespace.IMyInterface"。またMetadata、エクスポートごとに正しくロードされます。

AllowMultipleセッターを削除して、エクスポートされた属性を 1 つだけ含めると、myExports変数には、ロードされたメタデータを含む単一のエクスポートが含まれるようになります。

私は何を間違っていますか?

編集:弱く型付けされたメタデータを使用すると、エクスポートが突然満足します:

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

理由はありますか?

4

1 に答える 1

10

MEF は、 を処理する際にいくつかの問題を抱えていることが知られていAllowMultiple = trueます。完全な説明については、たとえばhereを参照してください。とにかく、AllowMultiple が true の場合、値が配列である Dictionary にメタデータが保存され、そのようなものを IMyInterfaceInfo にマップできないという事実に由来します。

これは私が使用する回避策です。まず、属性は ExportAttribute からではなく、Attribute から派生する必要があります。

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

つまり、エクスポートされたクラスには、標準エクスポートとカスタム属性の 3 つの属性が必要です。

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

次に、インポートされるメタデータのビューを定義する必要があります。これには、IDictionary をパラメーターとして受け取るコンストラクターが必要です。このようなもの:

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

これで、正常に呼び出すことができるはずです

var myExports = CompositionContainer.GetExports<IMyInterface, MyInterfaceInfoView>();
于 2012-06-13T07:48:37.927 に答える