c# - CompositionContainer.SatisfyImportsOnce 是否重用组件?

标签 c# memory-leaks mef composition

在 WCF 服务项目中,我为 MEF CompositionContainer 创建了一个简单的包装器以简化其实例化:

internal class CompositionProxy
{
    private static Lazy<CompositionContainer> m_lazyCC;
    static CompositionProxy()
    {
        m_lazyCC = new Lazy<CompositionContainer>(() =>
            {
                var batch = new CompositionBatch();

                var dc1 = new DirectoryCatalog(
                    HttpContext.Current.Server.MapPath("~/bin")
                    );

                return new CompositionContainer(dc1);
            }
        );
    }
    public static CompositionContainer DefaultContainer
    {
        get
        {
            return m_lazyCC.Value;
        }
    }
}

这个想法是在应用程序生命周期内拥有一个 CompositionContainer,它在 bin 目录中搜索导出。

然后,我设置了一些网络服务,需要导入属性:

它们都是这样构建的:

public class MyService: IMyService
{
    public MyService()
    {
        CompositionProxy.DefaultContainer.SatisfyImportsOnce(this);
    }
    [Import]
    private IContext Context { get; set; }

    public void DoTheJob()
    {
        // Logic goes here
    }
}

在其他地方,我有一个与此导出匹配的类:

[Export(typeof(IContext))]
public class MyContext 
{
    public MyContext(){
        Log("MyContext created");
    }
}

在构造函数中,我要求组合容器填充 IContext Context 属性。

这似乎有效,在我的服务中,我可以看到 Context 属性已正确填充。

但是,我遇到了内存泄漏,并且我的跟踪显示 MyContext 类仅实例化一次。

你能澄清一下我是否误用了组合框架吗?

  1. 我认为在应用程序的生命周期内使用一个组合容器是个好主意,我错了吗?
  2. SatisfyImportsOnce 的多次调用似乎使用相同的唯一实例填充目标。是真的吗?如果是这样,我如何简单地更改代码以在每次调用该方法时都有一个新实例?
  3. 有任何改进我的代码的建议吗?

最佳答案

I supposed it's a good idea to have one composition container for the application lifetime

是的,您应该为应用程序的生命周期创建一个容器。

the multiple calls to SatisfyImportsOnce seems to populate the target with the same unique instance. Is it true ? If true, how can I simply change my code to have a new instance each time the method is called ?

您需要[Import(RequiredCreationPolicy=CreationPolicy.NonShared)]

Any suggestion to improve my code ?

如果可能,不要将容器公开为全局容器,并在代码中调用它。这就是服务定位器模式,与依赖注入(inject)相比,它有一些缺点。您的服务不必尝试自行组合,只需声明它需要什么即可:

[Export(typeof(IMyService))]
public class MyService: IMyService
{
    private readonly IContext context;

    public MyService(
        [Import(typeof(IContext),      
            RequiredCreationPolicy=CreationPolicy.NonShared)]
        IContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");
        this.context = context;
    }

    public void DoTheJob()
    {
        // Logic goes here
    }
}

在 WCF 服务中,我认为您应该只需要在 ServiceHostFactory 实现中调用容器。不过我对 WCF 不太熟悉。

关于c# - CompositionContainer.SatisfyImportsOnce 是否重用组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7552483/

相关文章:

c# - 集中 MEF 组合

mvvm - 添加 View 不会调用MEF导入语句

java - 一个应用程序中的数据库连接泄漏是否会影响服务器中的其他应用程序?

memory-leaks - Ninject 中的内存泄漏

c# - 如何在 MySQL 数据库中使用系统时间查询搜索时间

c# - 当这种情况发生时如何通知一个人?

android - 应用程序加载时分配大内存

c# - 我如何处理 MEF 中具有相同依赖项的不同版本的模块?

C# 字典包含键/TryGetValue 不工作

c# - 有效处理设置