如何在MEF中使用事件聚合器?

时间:2014-02-21 19:23:19

标签: c# .net prism mef prism-4

我正在运行最新的PRISM 4.2。不幸的是,文档中的Event Aggregator教程是通过Unity而不是MEF驱动的。我无法在MEF下运行它。

App.xaml.cs

 public partial class App : Application
    {
        [Import]
        public IEventAggregator eventAggregator;

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            Bootstrapper bootstrapper = new Bootstrapper();
            bootstrapper.Run();
        }
    }

Bootstrapper.cs

public class Bootstrapper : MefBootstrapper
    {
        protected override DependencyObject CreateShell()
        {
            return new MainWindow();
        }

        protected override void InitializeShell()
        {
            base.InitializeShell();
            App.Current.MainWindow = (Window)Shell;
            App.Current.MainWindow.Show();
        }

        protected override void ConfigureAggregateCatalog()
        {
            base.ConfigureAggregateCatalog();

            AggregateCatalog.Catalogs.Add(new AssemblyCatalog(this.GetType().Assembly));
        }

        protected override IModuleCatalog CreateModuleCatalog()
        {
            ModuleCatalog moduleCatalog = new ModuleCatalog();

            return moduleCatalog;
        }

    }

MainWindow.xaml.cs

public partial class MainWindow : Window, IView
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainViewModel();
        }
    }

MainViewModel.cs:

[ModuleExport(typeof(MainViewModel))]
    public class MainViewModel : BindableBase, IServiceCallback
    {
        [Import]
        public IEventAggregator eventAggregator;

        [ImportingConstructor]
        public MainViewModel()
        {            
            eventAggregator.GetEvent<AppExitEvent>().Publish("");

        }
     }

尽管[import]事件聚合器在App.xaml.cs和MainViewModel中始终为null。那是为什么?
第二个问题是我是否必须将我的Viewmodels导出为模块(如上所述)以在其中使用均匀聚合器?

更新

证明最新版本的PRISM不再支持ComposeExportedValue

enter image description here

  

&#39; System.ComponentModel.Composition.Hosting.CompositionContainer&#39;不   不包含&#39; ComposeExportedValue&#39;的定义没有延伸   方法......

4 个答案:

答案 0 :(得分:7)

对此的解决方案将是 SchubertJ CodePlex 的同一问题上回复:

作为更深入的分析,在构造函数完成之前,属性上的导入属性将无法解析。这就是为什么你需要通过构造函数注入 EventAggregator 依赖项作为参数,如果这个依赖项将用于构造函数实现。

因此,如果您想对 ViewModel 构造函数使用 EventAggregator 依赖关系,则应使用 [ImportConstructor] < / strong>属性,并通过将其作为参数进行检索,向容器询问 EventAggregator 实例:

public class MainViewModel
{
    private readonly IEventAggregator eventAggregator;

    [ImportingConstructor]
    public MainViewModel(IEventAggregator eventAggregator)
    {
       this.eventAggregator = eventAggregator;

       this.eventAggregator.GetEvent<MyEvent>().Publish("");
    }
}

您可以在以下帖子中找到有关这两种导入替代方案的更多相关信息:

我希望这有助于你,问候。

答案 1 :(得分:1)

在你的bootstrapper类中有这个方法:

protected override void ConfigureContainer()
{
     base.ConfigureContainer();
     Container.ComposeExportedValue(new EventAggregator());
}

你应该看一下这篇文章,因为它更详细地回答了你的第一个和第二个问题。 http://www.gonetdotnet.info/posts/wpf-articles/wpf-module-communication

更新

如果您创建如下所示的类,则会将导出与导入匹配。

public class EventAggProvider
   {
     [Export(typeof(IEventAggregator))]
     public IEventAggregator eventAggregator { get { return new EventAggregator(); } }
   }

答案 2 :(得分:1)

这有点晚了,但是对于你希望EventAggregator注入属性的情况也有一个解决方案。实施“ IPartImportsSatisfiedNotification ”并在“ OnImportsSatisfied ”方法中使用eventaggregator。

public class MainViewModel : BindableBase,  IPartImportsSatisfiedNotification
{
    [Import]
    public IEventAggregator eventAggregator;

    public void OnImportsSatisfied()
    {
        eventAggregator.GetEvent<AppExitEvent>().Publish("");
    }
 }

答案 3 :(得分:0)

EventAggregator不依赖于MEF or Unity由Martin Fowler创造的设计模式,而是基于发布商订阅者情景

尝试按照以下步骤操作

//这应该在你的基础设施层

public  static class EventAggregatorHelper
{
  private static IEventAggregator _Current = new EventAggregator();
  public static IEventAggregator Current
  {
    get
    {
      return _Current;
    }
  }
}



The HandleAppExitEvent is a class declared as shown below:

public class AppExitEvent : CompositePresentationEvent<String>
{
} 

and the subscriber would be something like this:
MainWindow.xaml.cs

中的

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainViewModel();  
 //In this case the HandleAppExitEvent and the subscriber that deals with this event.                   
 EventAggregatorHelper.Current.GetEvent<AppExitEvent>().   Subscribe(HandleAppExitEvent);  

            }
      //note that this method should be public 

 public void HandleAppExitEvent(string mess)
    {
       if (!String.IsNullOrEmpty(mess))
       {
          //Do whatever you need to do here.
       }
    }

    }