如何交换/替换MEF容器共享(单身)的对象? [英] How to exchange/replace the shared (singleton) object in MEF container?

查看:163
本文介绍了如何交换/替换MEF容器共享(单身)的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能是简单的,但因为我是新来的MEF的舞台,这就是为什么我有一些困难,找出解决我的问题。

This may be simple but as I am new to MEF arena that is why I am having some difficulty to figure out the solution to my problem.

我的工作使用WPF +棱镜与MEF作为DI容器的应用程序。我想通过它与文件相关联的每个应用程序实例,以配合我的对象(即 RuleFile )说RuleFile1.ruleapp。因此,我曾与属性来修饰它 [PartCreationPolicy(CreationPolicy.Shared)] ,使之保持在整个与每个应用程序实例的应用程序一样来对待它作为单。

I am working on an application using WPF + Prism with MEF as DI container. I want to tie my object (i.e. RuleFile) with each application instance by associating it with the file say RuleFile1.ruleapp. Therefore I have decorated it with attribute [PartCreationPolicy(CreationPolicy.Shared)] to treat it as singleton so that it remains same throughout the application with each application instance.

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

接下来,在视图模型的时间 [ ImportingContructor] 如下图所示,对象根据需要是一样的。

Next, at the time of ViewModel [ImportingContructor] as shown below, the object is same as desired.

[ImportingConstructor]
public RuleViewModel(RuleFile ruleFile)

[ImportingConstructor]
public SchemaViewModel(RuleFile ruleFile)

到现在为止一切顺利。

使用下面的代码片段,我试图让被传递给查看模式一样导出对象IRuleFile>以上但 container.GetExportedValue<提到的()正在给一个新的对象引用是不一样的一种:

Using below piece of code, i am trying to get the same exported object that is passing to view model as mentioned above but container.GetExportedValue<IRuleFile>() is giving a new object reference that is not the same one:

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



问1:为什么我得到一个不同的参考,虽然对象应该是同样的,因为它与 CreationPolicy.Shared

Question 1: Why i am getting a different reference although object should be the same as it is a singleton object with CreationPolicy.Shared?

问题2一个singleton对象:归根结底,这一切努力是交换/替换 RuleFile 与在MEF DI容器中的反序列化四分之一出口对象?

Question 2: Ultimately this all effort is to exchange/replace RuleFile exported object with the deserialized one in the MEF DI container?

推荐答案

您不要在MEF容器更换的情况下,这不是它的工作原理,以及它的危险,完全失控。 (同时请记住C#不是C,你可以简单地改变指向的对象)。假设一个类X从容器中获取一个实例,并在它传递这种情况下其他类Y.现在突然要取代该实例的工厂方法。首先,会有什么发生在旧的实例?处理完毕?不停地活着吗?邮寄给你奶奶?其次,如果X使用了 GetExportedValue 实例,你怎么来通知它的实例已经现在已经没有了,被别的东西所取代?你不能。第三,假设用于X 导入,而不是通过一些魔法它被告知,它的实例已经被取代。它是如何在现在反过来要通知Ÿ该实例被替换?你不能,除非你保持Y.等,等的列表,我希望这使得它在容器中明确取代的对象是不是一个好主意。

You don't replace instances in a MEF container, that is not how it works, and it's dangerous and completely unmanageable. (Also keep in mind C# is not C where you can simply change pointed-to objects). Suppose a class X gets an instance from the container and has a factory method in which it passes this instance another class Y. Now suddenly you want to 'replace' that instance. First of all, what would have to happen to the old instance? Disposed? Kept alive? Mailed to your grandmother? Second, if X got the instance using GetExportedValue, how are you going to notify it the instance it has is now gone and is replaced by something else? You can't.. Third, suppose X used Import instead and by some magic it gets notified that it's instance has been replaced. How is it now in turn going to notify Y that the instance is replaced? You can't, unless you keep a list of Y. Etc, etc. I hope this made it clear replacing objects in a container isn't a good idea.

有一对夫妇的事情可以做,但不是:

There are a couple of things you can do instead though:


  1. 只要确保你的RuleFile创建之前在容器中注入这是在任何地方进口。这也使最有意义:在我的印象RuleFile是某种应用范围的配置,所以希望这个配置设置,即使启动应用程序之前完全。覆盖 MefBootstrapper.ConfigureContainer ,反序列化你RuleFile实例,并使用 ComposeExportedValue 将其设置为在容器中的唯一实例。如果deserializition失败,您aither显示一个错误对话框,并中止您的应用程序,或者提供一个默认的配置,并注入了吧。

  1. Just make sure your RuleFile is created and injected in the container before it is imported anywhere. This also makes most sense: I have the impression RuleFile is some kind of application-wide configuration, so it is desirable this configuration is setup completely before the application even starts. Override MefBootstrapper.ConfigureContainer, deserialize you RuleFile instance and use ComposeExportedValue to set it as the sole instance in the container. If deserializition fails, you aither show an error dialog and abort your app, or supply a default configuration and inject that instead.

提供的包装围绕RuleFile至极读从反序列化RuleFile如果可用,否则提供默认值。因此观察到的行为是相同的RuleFile在容器中被替换。然而,这具有重大的缺点,如果有使用IRuleFile实例加载该文件之前的代码,它得到不同的值比文件被加载之后。这就是为什么第一种方法比较好。例如:

Provide a wrapper around RuleFile wich reads from the deserialized RuleFile if available, or else supplies default values. So the observed behaviour is the same as RuleFile being replaced in the container. However this has the major drawback that if there is code using the IRuleFile instance before the file is loaded, it gets different values than after the file is loaded. Which is why the first approach is better. Example:

private class DefaultRuleFile: IRulefile
{
  string SomeProperty
  {
    get{ return "DefaultValue"; }
  }
}

[Export( typeof( IRulefile ) )]    
[Export( typeof( RuleFileImplementation ) )]    
[PartCreationPolicy(CreationPolicy.Shared)]
public class RuleFileImplementation : IRulefile
{
  private IRuleFile impl;

  RuleFileImplementation()
  {
    impl = new DefaultRuleFile();
  }

  string SomeProperty
  {
    get{ return impl.SomeProperty; }
  }

  void LoadFromFile( string file )
  {
    impl = SerializationHelper.Deserialize<IRuleFile>( file );
  }
}

//at some point in the application:
container.GetExportedValue<RuleFileImplementation>().LoadFromFile( "file" )


这篇关于如何交换/替换MEF容器共享(单身)的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆