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

您需要创建自己的目录。这不是一件容易的事,但这是一个例子 (我自己没有使用过。我可以用InheritedExport解决我的类似问题)

如果链接失效,我在这里重复代码。

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 回答