我真的喜欢MEF用于导出和导入但用于DI我更喜欢Unity 。这是我在尝试使用Unity解决懒惰列表时遇到的问题。
我导入ViewModelBases列表:
[ImportMany]
public IEnumerable<Lazy<ViewModelBase, ViewModelMetadata>> ViewModelsLazy { get; set;}
这很好用,但是当对象初始化时,我想用Unity解析他们的构造函数参数:
ViewModelsLazy.Single(v => v.Metadata.Name.Equals(viewModel)).Value
类似的东西:
unityContainer.Resolve<ViewModelsLazy.Single(v => v.Metadata.Name.Equals(viewModel)).Value>();
会很好。
我知道MEF使用[ImportingConstructor]
提供了Constructor-Injection,但是如前所述,我更喜欢Unity for DI,并且通常仅使用MEF进行导出/导入。
答案 0 :(得分:4)
您始终可以阅读目录以获取作为给定类型导出的类型。
此代码不会从[ImportMany]读取,而是可以分配IEnumerable而不是类上的ComposeParts。
MEF元数据也被剔除,使用这个元数据实际上需要实现接口。看起来你有一个名为ViewModelMetadata的类,它需要是一个接口。
public static class MEFExtensions
{
public static IEnumerable<Lazy<T, M>> GetExportsResolved<T, M>(this CompositionContainer mefContainer,
IUnityContainer unityContainer)
where T: class where M: class
{
// wrap the resolve around unity resolve then change type to T
return mefContainer.GetExportTypesWithMetadata<T, M>()
.Select(kv => new Lazy<T, M>(() => unityContainer.Resolve(kv.Key) as T, kv.Value));
}
public static IEnumerable<KeyValuePair<Type, M>> GetExportTypesWithMetadata<T, M>(
this CompositionContainer mefcontainer)
where T : class where M : class
{
// need to examine each type to see if they have the correct export attribute and metadata
foreach (var type in mefcontainer.GetExportTypes<T>())
{
// should just be one if more than one will throw exception
// metadata or export attribute has to implement the interface
var metadataAttribute =
type.GetCustomAttributes()
.SelectMany(
a =>
a.GetType()
.GetCustomAttributes()
.OfType<MetadataAttributeAttribute>()
.Concat<Attribute>(new[] { a }.OfType<ExportAttribute>()))
.OfType<M>().SingleOrDefault();
// if we found the correct metadata
if (metadataAttribute != null)
{
// return the lazy factory
yield return new KeyValuePair<Type, M>(type, metadataAttribute);
}
}
}
//Idea from http://www.codewrecks.com/blog/index.php/2012/05/08/getting-the-list-of-type-associated-to-a-given-export-in-mef/
public static IEnumerable<Type> GetExportTypes<T>(this CompositionContainer mefContainer)
where T : class
{
// look in the mef catalog to grab out all the types that are of type T
return mefContainer.Catalog.Parts.Where(part => part.ExportDefinitions
.Any(
def =>
def.Metadata.ContainsKey(
"ExportTypeIdentity") &&
def.Metadata["ExportTypeIdentity"]
.Equals(
typeof (T).FullName)))
.AsEnumerable()
.Select(part => ReflectionModelServices.GetPartType(part).Value);
}
}
看起来你也试图将它用作统一容器,最好只使用一个单位容器。我们目前使用MEF来查找所有注册 - 这些注册是具有如何注册的元数据的导出属性。然后执行类似上面的操作来填充统一容器而不是属性。
你会像
一样使用它ViewModelsLazy = mefContainer.GetExportsResolved<ViewModelBase, IViewModelMetadata>(unityContainer);
再次使用统一容器并执行类似
的操作可能会更好var regs = mefContainer.GetExportTypesWithMetadata<ViewModelBase, IViewModelMetadata>();
foreach (var reg in regs)
{
unityContainer.RegisterType(typeof (ViewModelBase), reg.Key, reg.Value.Name);
}
当你想要一个课程解决时,你会去团结并做一个决定,将名称作为合同名称传递。