CompositionContainer.SatisfyImportsOnce是否重用组件?

时间:2011-09-26 08:28:20

标签: 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目录中搜索导出。

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

所有这些都是这样构建的:

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的多次调用似乎使用相同的唯一实例填充目标。这是真的吗?如果为true,我怎样才能在每次调用方法时简单地更改我的代码以获得新实例?
  3. 有任何改进我的代码的建议吗?

1 个答案:

答案 0 :(得分:3)

  

我认为在应用程序生命周期内有一个合成容器是个好主意

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

  

对SatisfyImportsOnce的多次调用似乎使用相同的唯一实例填充目标。这是真的吗?如果为true,我怎样才能在每次调用方法时简单地更改我的代码以获得新实例?

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

  

有任何改进我的代码的建议吗?

如果可能,请不要将容器公开为全局容器,并通过调用它来丢弃代码。这就是服务定位器模式,与依赖注入相比,它有一些缺点。而不是你的服务试图自己组成,只需声明它需要的东西:

[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。