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();
    }
}