In a WCF service project, I have created a simple wrapper for MEF CompositionContainer to simplify its instantiation :
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;
}
}
}
The idea is to have one CompositionContainer for the application lifetime, which search for export in the bin directory.
Then, I set up some webservices, that requires to have on imported property :
All of them are built like this :
public class MyService: IMyService
{
public MyService()
{
CompositionProxy.DefaultContainer.SatisfyImportsOnce(this);
}
[Import]
private IContext Context { get; set; }
public void DoTheJob()
{
// Logic goes here
}
}
Elsewhere, I have one class that match this export :
[Export(typeof(IContext))]
public class MyContext
{
public MyContext(){
Log("MyContext created");
}
}
In the constructor, I ask the composition container to populate the IContext Context property.
This seems to work, in my service, I can see the Context property is correctly populated.
However, I’m experiencing memory leaks, and my tracing show me the MyContext class is instantiated only once.
Can you clarify if I’m misusing the composition framework ?
- I supposed it’s a good idea to have one composition container for the application lifetime, was I wrong ?
- the multiple calls to
SatisfyImportsOnceseems 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 ? - Any suggestion to improve my code ?
Yes, you are supposed to create one container for the application lifetime.
You need
[Import(RequiredCreationPolicy=CreationPolicy.NonShared)].If possible, do not expose the container as a global and litter your code with calls to it. That’s the Service Locator pattern, which has some disadvantages when compared to Dependency Injection. Instead of your service trying to compose itself, just declare what it needs:
In a WCF service, I think you should only need to call the container in your
ServiceHostFactoryimplementation. I’m not really familiar with WCF though.