我正在使用MEF2,并阅读了一些关于MEF1和MEF2的教程。
到目前为止,我发现的最好的是这个:http://www.codeproject.com/Articles/366583/MEF-Preview-Beginners-Guide
虽然我确实让导出工作得很好,但我真的想使用属性样式,因为在接口上使用InheritedExport似乎比在我声明的接口和容器约定之间来回切换方便得多。
这是我的代码片段:
var convention = new ConventionBuilder();
convention.ForTypesDerivedFrom<IMainTabsControl>().Export<IMainTabsControl>();
convention.ForTypesDerivedFrom<IShell>().Export<IShell>().Shared();
// here is where i am struggeling.
convention.ForTypesMatching(type => typeof (ICrawlerKeyProvider).IsAssignableFrom(type)).Export(builder => builder.AsContractType(typeof(bool)));
var configuration = new ContainerConfiguration();
MefContainer = configuration.WithAssemblies(new []{ Assembly.GetExecutingAssembly(), }, convention).CreateContainer();
所以实际上有三种选择:
- 我在MEF2中找不到重命名的功能
- 我用的方法不对
- 我错过了一些显而易见的东西
据我所知,这应该很容易:
- 检查(自定义)属性的类型
- 为包含所需属性的类型提取所需导出类型
- 完成导出
但使用ForTypesMatching,我似乎无法执行我想要的操作,因为没有可用于构建器变量的类型信息。
奇怪的是,我是否试图做一些在MEF2中不可能,但在MEF1中可能的事情
更新:
有趣的阅读:http://blog.slaks.net/2014-11-16/mef2-roslyn-visual-studio-compatibility/
属性:
public class ExportAsAttribute : Attribute
{
public Type ContractType { get; set; }
public string ContactName { get; set; }
public ExportAsAttribute(Type contractType)
{
ContractType = contractType;
}
public ExportAsAttribute(Type contractType, string contactName)
{
ContactName = contactName;
ContractType = contractType;
}
}
公约代码:
var allTypes = GetAllAssemblies().SelectMany(d => d.ExportedTypes);
foreach (var type in allTypes)
{
var attr = type.GetCustomAttribute<ExportAsAttribute>(true);
if (attr != null)
{
foreach (var derivedType in allTypes.Where(d => !d.IsAbstract && !d.IsInterface && type.IsAssignableFrom(d)))
{
if (string.IsNullOrEmpty(attr.ContactName))
{
convention.ForType(derivedType).Export(config => config.AsContractType(attr.ContractType));
}
else
{
convention.ForType(derivedType).Export(config => config.AsContractType(attr.ContractType).AsContractName(attr.ContactName));
}
}
}
}