3

この質問への回答に基づいて、CompositionBatchとカタログの違いは何ですか?これは、オブジェクトが他のコンポーネントによって構築されている状況で、構成バッチの使用が役立つことを示しています。これは私に考えさせられました、それはどのような実際の例に適用されますか?それから私はあなたがコントロールできないビルドされるオブジェクトについて考え始めました。エクスポートとしてマークされていないパーツを追加できない場合、これらのインスタンスをコンテナにどのように追加しますか?頭に浮かぶのは、目的のタイプのメンバーでクラスを設定し、それをエクスポートとしてマークすることだけです。

インスタンスがエクスポートとしてマークされていない場合、インスタンスをコンテナに追加することは可能ですか?

4

2 に答える 2

6

「インスタンス」ではなく「エクスポートとしてマークされていないクラス」を意味していると仮定します。

.NET4.5以降では、 MEFのコンベンションモデルを使用できます。

.NET4の場合、Mark Seemannは、ジェネリックスとプロパティのエクスポートを巧みに利用して既存の型をエクスポートする方法についてブログに書いています。次のようなクラスを作成できます。

public class MefAdapter<T> where T : new()
{
    private readonly T export;

    public MefAdapter()
    {
        this.export = new T();
    }

    [Export]
    public virtual T Export
    {
        get { return this.export; }
    }
}

次に、タイプカタログを作成して、MEFに対応していない既存のタイプを次のようにエクスポートできます。

var catalog = new TypeCatalog(
    typeof(MefAdapter<Foo>),
    typeof(MefAdapter<Bar>), 
    ...);

この例を変更して、コンストラクター引数を持つ型のサポートを追加したり、クラス型だけでなくインターフェイスをエクスポートしたりすることもできます。

于 2012-06-20T10:37:21.157 に答える
2

独自のカタログを作成する必要があります。これは簡単な作業ではありませんが、ここに例を示します (私はそれを自分で使用していません。ヘリテッドエクスポートで同様の問題を解決できます

リンクが切れた場合は、ここでコードを繰り返します。

public class ConventionalCatalog : ComposablePartCatalog {
    private List<ComposablePartDefinition> _parts = new List<ComposablePartDefinition>();
    public void RegisterType<TImplementation, TContract>() {
        var part = ReflectionModelServices.CreatePartDefinition(new Lazy<Type>(() => typeof(TImplementation)),
                   false,
                   new Lazy<IEnumerable<ImportDefinition>>(() => GetImportDefinitions(typeof(TImplementation))),
                   new Lazy<IEnumerable<ExportDefinition>>(() => GetExportDefinitions(typeof(TImplementation), typeof(TContract))),
                   new Lazy<IDictionary<string, object>>(() => new Dictionary<string, object>()),
                   null);
                   _parts.Add(part);
    }

    private ImportDefinition[] GetImportDefinitions(Type implementationType) {
        var constructors = implementationType.GetConstructors()[0];
        var imports = new List<ImportDefinition>();

        foreach (var param in constructors.GetParameters()) {
            imports.Add(ReflectionModelServices.CreateImportDefinition(
                new Lazy<ParameterInfo>(() => param),
                AttributedModelServices.GetContractName(param.ParameterType),
                AttributedModelServices.GetTypeIdentity(param.ParameterType),
                Enumerable.Empty<KeyValuePair<string,Type>>(),
                ImportCardinality.ExactlyOne,
                CreationPolicy.Any,
                null));
        }
        return imports.ToArray();
    }

    private ExportDefinition[] GetExportDefinitions(Type implementationType, Type contractType) {
        var lazyMember = new LazyMemberInfo(implementationType);
        var contracName = AttributedModelServices.GetContractName(contractType);
        var metadata = new Lazy<IDictionary<string, object>>(() => {
                           var md = new Dictionary<string, object>();
                           md.Add(CompositionConstants.ExportTypeIdentityMetadataName,
                                  AttributedModelServices.GetTypeIdentity(contractType));
                           return md;
                       });
        return new ExportDefinition[] {
             ReflectionModelServices.CreateExportDefinition(lazyMember, contracName, metadata, null)
        };
    }

    public override IQueryable<ComposablePartDefinition> Parts {
        get { return _parts.AsQueryable(); }
    }
}

次のように使用します。

using (var myCatalog = new ConventionalCatalog()) {
    myCatalog.RegisterType<MyClass, IMyClass>();

    using (var container = new CompositionContainer(myCatalog)) {
        container.ComposeParts(this);
        ...
    }
}
于 2012-06-20T06:08:46.327 に答える