3

.NET Framework ベースのアプリケーションのコレクションを .NET Core に移植しようとしています。このプロセスの一環として、MEF1 の使用から MEF2 の使用に切り替える必要があります。私は MEF2 に関連する問題に頭を悩ませていましたが (この投稿は非常に役に立ちました)、最近、問題の 1 つの背後にある理由に出くわしました。

特に、カスタムExportAttributeを使用してメタデータをエクスポートする多くのクラスがあり、それらすべてを別のクラスにインポートして、このメタデータに基づいてフィルタリングしたいと考えています。これは MEF1 ではすべて正常に機能していましたが、MEF2 では「xのエクスポート メタデータが見つからず、デフォルト値が指定されていません」などの問題に遭遇しました。

より具体的には、エクスポートしたクラスに次のように注釈を付けます。

[Export(typeof(IClientRequestProcessor<RelaySystemModel>))]
[TargetDevice("<<Foo>>")]
internal class RelaySystemClientRequestProcessor : IClientRequestProcessor<RelaySystemModel>
{
}

次に、他の場所で、次のようにインポートしようとします。

[ImportMany]
public IEnumerable<ExportFactory<IClientRequestProcessor<RelaySystemModel>, DeviceSpecific>> RelayRequestProcessors { private get; set; }

そして、インポートが完了したら、メタデータでフィルター処理を試みます。

private static IEnumerable<ExportFactory<T, DeviceSpecific>> FilterForFoo<T>(IEnumerable<ExportFactory<T, DeviceSpecific>> items)
{
    return from it in items where it.Metadata.DeviceId == "<<Foo>>" select it;
}

は次TargetDeviceAttributeのように定義されます。

[MetadataAttribute, AttributeUsage(AttributeTargets.Class)]
public class TargetDeviceAttribute : ExportAttribute, IDeviceSpecific
{
    public TargetDeviceAttribute(string deviceId)
    {
        this.DeviceId = deviceId;
    }

    public string DeviceId { get; private set; }
}

何が起こっているかというと、パーツ が 2つのエクスポートRelaySystemClientRequestProcessorに対応していることがわかりました。ただし、「DeviceId」メタデータは後者にのみ関連付けられており、前者には関連付けられていないため、役に立ちません。IClientRequestProcessor<RelaySystemModel>RelaySystemClientRequestProcessor

MEF2-エクスポート

完全にテストしていませんが、これを解決できると思われる方法がいくつかあります。

  1. ExportMetadata("DeviceId", "<<foo>>")エクスポートされたすべてのパーツに属性を適用します。

  2. TargetDeviceAttributeコンストラクターを使用するように変更しますpublic TargetDeviceAttribute(string deviceId, Type exportType) : base(exportType)

私はこれらの解決策に賛成ではありません。前者はメタデータ キーを変更したい場合に問題があり、どちらもすべてのパーツをエクスポートする方法を変更する必要があります。

私が疑問に思っているのは、MEF2 が MEF1 のようにメタデータをエクスポートする方法を提供するかどうかです: カスタム メタデータ属性を作成し、そのメタデータをパーツに関連付けられたすべてのエクスポートに適用します。これは可能ですか?

4

1 に答える 1

1

6文字を削除する必要があったことがわかりました。TargetDeviceAttributeinherit fromを作成する代わりに、代わりにfrom を継承ExportAttributeする必要がありAttributeます。

[MetadataAttribute, AttributeUsage(AttributeTargets.Class)]
public class TargetDeviceAttribute : Attribute, IDeviceSpecific
{
    public TargetDeviceAttribute(string deviceId)
    {
        this.DeviceId = deviceId;
    }

    public string DeviceId { get; private set; }
}

より一般的なケースでは、これは、複数の可能なタイプに関連付けることができるメタデータを意味しますが、ExportAttribute("foo", "bar")以下のようなことを行う必要があると思われるよりも、より優れた静的タイプの安全性/保守性を確保する必要があります。

public interface IMetadataExtension
{
    string Foo { get; }
}

public class MetadataExtension : IMetadataExtension
{
    public string Foo { get; set; }
}

[MetadataAttribute]
public class MetadataExtensionAttribute : Attribute, IMetadataExtension
{
    public MetadataExtensionAttribute(string foo)
    {
        Foo = foo;
    }

    public string Foo { get; }
}

[Export]
[MetadataExtension("bar")]
public class SomeExport
{

}
于 2016-10-04T12:02:41.033 に答える