如何告诉MEF重新创建对象?

kat*_*tit 3 wcf mef inversion-of-control

我正在使用mef创建WCF Web服务。服务外观如下:

[Export]
    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class MobileService
    {
        [Import] 
        public IEmailService EmailService { get; set; }

        [Import] 
        public ILoggerService LoggerService { get; set; }

        [Import] 
        public IContextManager ContextManager { get; set; }
Run Code Online (Sandbox Code Playgroud)

这是获取服务实例的代码的外观:

// Get Service instace via MEF        
    public object GetInstance(InstanceContext instanceContext, Message message)
    {
        var lazyInstance = Container.GetExports(ServiceType, null, null).FirstOrDefault();
        var instance = lazyInstance.Value;

        return instance;
    } 
Run Code Online (Sandbox Code Playgroud)

MEF创建了EmailService,LoggerService,如果可以的话,它们会在服务有效期内快乐地生活。

现在,ContextManager是另一种动物。在GetInstance中-我真的很想“杀死”它并重新创建。ContextManager在构造过程中研究URL和标题,并填充“上下文”。使用像我一样的代码-它是第一次创建的,永远不会被破坏。如何改变这种行为?

谢谢!

Tim*_*rts 5

在导出IContextManager的实现时,您需要使用非共享零件创建策略标记导出。例如:

[Export(typeof(IContextManager)]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ContextManager : IContextManager
{
   ...
}
Run Code Online (Sandbox Code Playgroud)

这将通知MEF,每当满足导入条件时,都应创建一个新的导出实例。默认情况下,MEF使用CreationPolicy.Shared创建仅一个导出的值(单例),这可能是您希望在Email和Logging实现中使用的值。

  • 请注意,如果您导入诸如Lazy <IContextManager>之类的内容,则由于Lazy <>总是会得到相同的实例,无论CreationPolicy是非共享还是共享。想象一下[ImportMany]和元数据的情况 (3认同)
  • 为了弄清blindmeis的评论,如果您在Lazy <IContextManager>的两个不同实例上调用.Value,则非共享零件创建策略会确实导致不同的实例。如果您从同一对象中的同一个懒惰导入中重复检索`.Value`,则只有同一个上下文管理器实例。 (2认同)