4

これは私の最初のSOの質問ですので、ご容赦ください...

ConventionBuilder クラスを使用して MEF2 でコンポーネントをロードしようとしています。インポートされた型の属性として利用できるメタデータにアクセスする必要があるまで、すべてが期待どおりに機能します。次のクラスがあるとします。

[RuntimeCheckAttribute("MyString1", "MyString2", MyEnum.Value1)]
class ImportedClass : IRuntimeCheck
{...}

これで、「IRunTimeCheck」のインスタンスの規則を定義する ConventionBuilder インスタンスを作成できます。

ConventionBuilder conventions = new ConventionBuilder();
conventions.ForTypesDerivedFrom<IRuntimeCheck>()
           .Export(exp => exp.AsContractType<IRuntimeCheck>()).Shared();

次に、アセンブリのリストを検査するように構成された「CompositionHost」インスタンスを利用します。への呼び出し

var runtimeChecks = container.GetExports<IRuntimeCheck>();

次に、エクスポートされたすべての「IRuntimeCheck」タイプのインスタンスを作成します。

私の質問は、エクスポート プロセス中に IRunTimeCheck 型のメタデータにアクセスする方法です。MEF1 では、ImportMany / Lazy メカニズムを利用できました。「CompositionHost」のすべてのエクスポート オーバーロードではメタデータ属性にアクセスできないため、これまで MEF2 でこの動作を再構築する良い方法を見つけていませんでした。

AddPartMetaData を使用して、ConventionBuilder レベルでメタデータを追加することができました。

conventions.ForTypesDerivedFrom<IRuntimeCheck>()
           .AddPartMetadata("securityRuntimeMetadata", AddRuntimeCheckMetadata)
           .Export(exp => exp.AsContractType<IRuntimeCheck>()).Shared();

private object AddRuntimeCheckMetadata(Type arg)
{
    RuntimeCheckAttribute metadata = (arg.GetCustomAttributes<RuntimeCheckAttribute>(false) as  
                                            RuntimeCheckAttribute[]).FirstOrDefault();
    if (metadata == null)
    {
        throw new InvalidOperationException("errorMessage");
    }
    return metadata;
}

MEF2 コードをデバッグすると、メタデータ情報が規約ビルダー レベルで追加されていることがわかります。しかし、この情報を再度エクスポートする方法がわかりませんでした。ExportFactory を利用しようとする投稿がいくつか見つかりました。しかし、それらのほとんどは、私の目標ではない非共有エクスポートで作業しています。

4

1 に答える 1

2

コメントとして書いたように、同様の問題がありました。いくつか遊んでコードをステップインした後、型をインスタンス化せずに必要なメタデータを取得しました。

これは私のConventionBuilder構成です:

var cb = new ConventionBuilder();
cb.ForTypesDerivedFrom<IHttpController>()
            .AddPartMetadata(MetadataApiControllerName, t => t.FullName)
            .Export(ex => ex.AddMetadata(MetadataApiControllerName, t => t.FullName))
            .ExportInterfaces();

cb.ForTypesMatching(t => t.BaseType != null && (
                    (t.BaseType.Name.Equals(MetadataControllerName) && !t.BaseType.Name.StartsWith("T4MVC"))
                    || t.BaseType.Name.Equals(MetadataExtentionControllerName)
                    ))
                .AddPartMetadata(MetadataControllerName, t => t.FullName)
                .Export(ex => ex.AddMetadata(MetadataControllerName, t => t.FullName))
                .ExportInterfaces();

私は MVC / Web Api プロジェクトに取り組んでおり、一部のコントローラーのメタ情報のみが必要です。それらを取得するには、次のエクスポートを使用します。

var controllerExport = _compositionContainer.Container.Value.GetExports<ExportFactory<IController, IDictionary<String, Object>>>()
                    .FirstOrDefault(
                        part => part.Metadata != null &&
                                part.Metadata.ContainsKey(DefaultContainerConfiguration.MetadataControllerName) &&
                                part.Metadata.Any(v => v.Value.ToString()
                                                .EndsWith(controllerName + ControllerNameByConvention, true,
                                                CultureInfo.InvariantCulture)));

ExportFactory オブジェクトは、要求されたメタデータ ディクショナリ ( IDictionary<String, Object>) を提供します。

于 2014-08-20T09:34:29.887 に答える