Reputation: 16708
I have an object as shown below.
[Serializable()]
[Export(typeof(IRuleFile))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class RuleFile : NotifyPropertyChanged, IRuleFile { }
Using [ImportConstructor]
or [Import]
, same object reference is returned.
But by using programmatic approach the object returned is different although it should be singleton, why?
var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
var exportedObj = container.GetExportedValue<IRuleFile>();
ADDED
I have two view model in my solution, below i am showing only one but at the [ImportConstructor]
object remain same but upon using GetExportedValue
i get a new instance and constructor is invoking again.
[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);
}
}
My actual intend is to replace the object back in the MEF container after deserialization so that object remain the same.
Upvotes: 1
Views: 996
Reputation: 35901
The reason two instances are being created is that your code uses two different AssemblyCatalog
and CompositionContainer
instances, and those are completely independent. So when using Import
and the likes, MEF uses the global container instance created in the bootstrapper. However in LoadRuleState you create a new container, which is empty and doesn't know about existing instances of any object, and hence creates a new RuleFile when you ask for it.
The usual trick when you want to work with the CompositionContainer outside of the bootstrapper is to simply add it to itself:
public class MefMuiBootstrapper : MefBootstrapper
{
protected override void ConfigureContainer()
{
base.ConfigureContainer();
Container.ComposeExportedValue( Container );
}
}
and then you can Import it like any other Export:
[Export]
public class ViewModel
{
private readonly CompositionContainer container;
[ImportingConstructor]
public ViewModel( CompositionContainer container )
{
this.container = container;
}
public void Load()
{
var exportedObj = container.GetExportedValue<IRuleFile>();
}
}
Upvotes: 1