开发者

Does CompositionContainer.SatisfyImportsOnce reuse components?

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 ?

  1. I supposed it's a good idea to have one composition container for the application lifetime, was I wrong ?
  2. 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 ?
  3. Any开发者_开发技巧 suggestion to improve my code ?


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

Yes, you are supposed to create one 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 ?

You need [Import(RequiredCreationPolicy=CreationPolicy.NonShared)].

Any suggestion to improve my code ?

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:

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

In a WCF service, I think you should only need to call the container in your ServiceHostFactory implementation. I'm not really familiar with WCF though.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜