C# 满意进口vs组件
有人能解释一下C# 满意进口vs组件,c#,mef,C#,Mef,有人能解释一下满意度导入和组件之间的区别,以及为什么一个可以工作而另一个不能工作 具体来说,我有一个使用MEF的MVC Web应用程序。下面是一些代码(来自该应用程序),在我使用SatisfyImportsOnce时有效,但在我使用ComposeParts时无效。我的理解是,composeports从属性化对象数组创建可组合的部分,并在指定的组合容器中组合它们,SatisfyImportsOnce通过使用指定的组合服务组合指定的部分。对我简单的猴脑来说,尽管英语不同,但它们在语义上是相同的。两者
满意度导入
和组件
之间的区别,以及为什么一个可以工作而另一个不能工作
具体来说,我有一个使用MEF的MVC Web应用程序。下面是一些代码(来自该应用程序),在我使用SatisfyImportsOnce
时有效,但在我使用ComposeParts
时无效。我的理解是,composeports
从属性化对象数组创建可组合的部分,并在指定的组合容器中组合它们,SatisfyImportsOnce
通过使用指定的组合服务组合指定的部分。对我简单的猴脑来说,尽管英语不同,但它们在语义上是相同的。两者都使用CompositionContainer
在导入目标上吐出导出的类型
public class FormPartCustomatorFactory
{
[ImportMany(typeof(ICustomRenderer), AllowRecomposition = true)]
private readonly List<Lazy<ICustomRenderer, ICustomRendererMetaData>> _rendererImports = new List<Lazy<ICustomRenderer, ICustomRendererMetaData>>();
private readonly Dictionary<string, Lazy<ICustomRenderer, ICustomRendererMetaData>> _renderers;
public static readonly FormPartCustomatorFactory Instance = new FormPartCustomatorFactory();
static CompositionContainer _container;
private FormPartCustomatorFactory()
{
using (var catalog = new DirectoryCatalog(HttpRuntime.BinDirectory, "*.dll"))
{
_container = new CompositionContainer(catalog);
_container.SatisfyImportsOnce(this); // <- Works
// _container.ComposeParts(this); // DOESN'T Work
_renderers = _rendererImports.ToDictionary(q => q.Metadata.Name, q => q);
}
}
~FormPartCustomatorFactory()
{
_container.Dispose();
}
public static ICustomRenderer Find(string name)
{
return Instance._renderers[name].Value;
}
}
公共类FormPartCustomatorFactory
{
[ImportMany(typeof(ICustomRenderer),AllowRecomposition=true)]
私有只读列表_renderImports=新列表();
私有只读字典_呈现器;
公共静态只读FormPartCustomatorFactory实例=新FormPartCustomatorFactory();
静态合成容器_容器;
私有FormPartCustomatorFactory()
{
使用(var catalog=newdirectorycalog(HttpRuntime.BinDirectory,“*.dll”))
{
_容器=新的合成容器(目录);
_container.SatisfyImportsOnce(this);//SatisyImportsOnce
将组成一个类型,而不注册它进行重新编译。因此,如果您打算使用不支持重新编译的类型,可以使用SatisfyImportsOnce
,它将像往常一样完成工作,但容器中的任何更改(添加或删除新部件),则不会自动重新组合实例以提供这些新部件
在您的实例中,您正在使用:
[ImportMany(typeof(ICustomRenderer), AllowRecomposition = true)]
…但通过SatisfyImportsOnce
,不会重新组合此导入
如果您不担心重新编译,您可以使用构造函数注入更改代码,以便执行以下操作:
[ImportingConstructor]
public FormPartCustomatorFactory(IEnumerable<Lazy<ICustomRenderer, ICustomRendererMetadata>> renderers)
{
if (renderers == null)
throw new ArgumentNullException("renderers");
_renderers = renderers.ToDictionary(r => r.Metadata.Name, r => r);
}
这样做意味着您的类型不依赖于MEF,它可以在没有MEF的情况下使用,它更易于测试,并且合成容器
将管理部件的寿命,在这种情况下,CreationPolicy.Shared
(这是导出类型的默认值),使用单例生存期策略。然后可以导入IFormPartCustomator
的实例,导入相同的单例实例
我还认为,将其称为工厂
可能是错误的,因为工厂旨在创建新实例,而您的类型只会为每个ICustomRenderer
创建一个实例。如果这是预期的行为,那么最好将其称为formpartcustomorservice
,它实现了de>IFormPartCusomatorService
接口?如果您想每次启动新实例,您可以查看ExportFactory
,正如Matthew提到的那样,SatisfyImportsOnce
不会注册要重新编译的部件。这意味着MEF容器不包含对该部件的引用
此外,
SatisfyImportsOnce
仅满足零件的导入,但忽略其具有的任何导出。ComposeParts
也会将导出添加到容器中。“ComposeParts也会将导出添加到容器中。”-这就是我想要的:)
public interface IFormPartCustomatorFactory
{
ICustomRenderer Find(string name);
}
[Export(typeof(IFormPartCustomerFactory)), PartCreationPolicy(CreationPolicy.Shared)]
public class FormPartCustomatorFactory : IFormPartCustomatorFactory
{
private IEnumerable<Lazy<ICustomRenderer, ICustomRendereMetadata>> _renderers;
[ImportingConstructor]
public FormPartCustomatorFactory(IEnumerable<Lazy<ICustomRenderer, ICustomRendererMetadata>> renderers)
{
if (renderers == null)
throw new ArgumentNullException("renderers");
_renderers = renderers;
}
public ICustomRenderer Find(string name)
{
return _renderers
.Where(r => r.Metadata.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)
.Select(r => r.Value)
.FirstOrDefault();
}
}