我有一个如下所示的对象。
[Serializable()]
[Export(typeof(IRuleFile))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class RuleFile : NotifyPropertyChanged, IRuleFile { }
使用[ImportConstructor]
或[Import]
,返回相同的对象引用。
但是通过使用编程方法,返回的对象是不同的,尽管它应该是单例,为什么?
var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
var exportedObj = container.GetExportedValue<IRuleFile>();
ADDED
我的解决方案中有两个视图模型,下面我只显示一个,但[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容器中,以便对象保持不变。
答案 0 :(得分:1)
创建两个实例的原因是您的代码使用了两个不同的AssemblyCatalog
和CompositionContainer
个实例,而这些实例完全独立。因此,当使用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>();
}
}