1

我有一个如下所示的对象。

[Serializable()]
[Export(typeof(IRuleFile))]    
[PartCreationPolicy(CreationPolicy.Shared)]
public class RuleFile : NotifyPropertyChanged, IRuleFile { }

使用[ImportConstructor]or [Import],返回相同的对象引用。

但是通过使用编程方法返回的对象是不同的,虽然它应该是单例的,为什么?

var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
var exportedObj = container.GetExportedValue<IRuleFile>();

添加

我的解决方案中有两个视图模型,下面我只显示一个,但[ImportConstructor]对象保持不变,但使用时GetExportedValue我得到一个新实例并且构造函数再次调用。

[Export]
[PartCreationPolicy(CreationPolicy.Shared)]
public partial class RuleViewModel : ViewModelBase
{
    [ImportingConstructor]
    public RuleViewModel(IRuleFile ruleFile)
    {
        RuleFile = ruleFile; // here the object is fine            
    }

    // this method triggers at the time of loading rule file
    public void LoadRuleState()
    {
        var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
        var container = new CompositionContainer(catalog);
        // at this point contructor triggers again in my case
        var exportedObj = container.GetExportedValue<IRuleFile>(); 

        // my intend is to replace the object back in the container after deserialization.
        RuleFile = SerializationHelper.DeserializeFromFile<RuleFile>(Constants.RuleDefinitionPath);
        container.ComposeExportedValue<IRuleFile>(RuleFile);
    }
}

我的实际意图是在反序列化后将对象替换回 MEF 容器中,以使对象保持不变。

4

1 回答 1

1

创建两个实例的原因是您的代码使用了两个不同AssemblyCatalogCompositionContainer实例,并且它们是完全独立的。所以在使用Import之类的时候,MEF 使用的是在引导程序中创建的全局容器实例。但是,在 LoadRuleState 中,您创建了一个新容器,该容器是空的并且不知道任何对象的现有实例,因此在您请求时会创建一个新的 RuleFile。

当您想在引导程序之外使用 CompositionContainer 时,通常的技巧是简单地将其添加到自身:

public class MefMuiBootstrapper : MefBootstrapper
{
  protected override void ConfigureContainer()
  {
    base.ConfigureContainer();
    Container.ComposeExportedValue( Container );
  }
}

然后您可以像任何其他导出一样导入它:

[Export]
public class ViewModel
{
  private readonly CompositionContainer container;

  [ImportingConstructor]
  public ViewModel( CompositionContainer container )
  {
    this.container = container;
  }

  public void Load()
  {
    var exportedObj = container.GetExportedValue<IRuleFile>();
  }
}
于 2014-09-02T07:31:27.923 回答