在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
类只被实例化一次。
你能否澄清一下我是否滥用了作文框架?
SatisfyImportsOnce
的多次调用似乎使用相同的唯一实例填充目标。这是真的吗?如果为true,我怎样才能在每次调用方法时简单地更改我的代码以获得新实例?答案 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。