Caliburn第4部分 事件聚合器

The event aggregator is a service that makes it easy for multiple parts of your application to send messages to each other.

要做到这一点,你订阅的​​事件聚合的对象(如视图模型),并指定他们应该听什么类型的消息。

现在做一个Colorviewmodel,在Appviewmodel中实现下列代码

public class Appviewmodel : PropertyChangedBase
{
  public Appviewmodel(Colorviewmodel colorModel)
  {
    ColorModel = colorModel;
  }
 
  public Colorviewmodel ColorModel { get; private set; }
}


<Grid Width="300" Height="300" Background="LightBlue">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>
  <ContentControl Name="ColorModel" Margin="10" />
</Grid>


AppBootstrapper 为了支持含有参数的构造函数

Make sure to include a reference to System.ComponentModel.Composition.dll to the application

using Caliburn.Micro;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
 
public class AppBootstrapper : Bootstrapper<Appviewmodel>
{
  private CompositionContainer container;
 
  protected override void Configure()
  {
    container = new CompositionContainer(new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()));
 
    CompositionBatch batch = new CompositionBatch();
 
    batch.AddExportedValue<IWindowManager>(new WindowManager());
    batch.AddExportedValue<IEventAggregator>(new EventAggregator());
    batch.AddExportedValue(container);
 
    container.Compose(batch);
  }
 
  protected override object GetInstance(Type serviceType,string key)
  {
    string contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
    var exports = container.GetExportedValues<object>(contract);
 
    if (exports.Count() > 0)
    {
      return exports.First();
    }
 
    throw new Exception(string.Format("Could not locate any instances of contract {0}.",contract));
  }
}


Next,we need to include an Export attribute on both our view-model classes. This is for the GetInstance method in the AppBootstrapper to work.

[Export(typeof(Appviewmodel))]
public class Appviewmodel : PropertyChangedBase
{
  ...
}
 
[Export(typeof(Colorviewmodel))]
public class Colorviewmodel
{
}


And finally,include the ImportingConstructor attribute on the Appviewmodel constructor.

This is to indicate that this constructor should be used since there is no default constructor. When Caliburn Micro creates the Appviewmodel,it will also create an instance of the Colorviewmodel to pass into the constructor for us.

[ImportingConstructor]
public Appviewmodel(Colorviewmodel colorModel)
{
  ColorModel = colorModel;
}


add a Rectangle into the second column

private SolidColorBrush _Color;
 
public SolidColorBrush Color
{
  get { return _Color; }
  set
  {
    _Color = value;
    NotifyOfPropertyChange(() => Color);
  }
}


<Rectangle Grid.Column="1" Width="100" Height="100" Fill="{Binding Color}" />



第2步:实施IHandle <TMessage>接口

We are going to be publishing messages from the Colorviewmodel to be picked up by the Appviewmodel.

添加一个消息类

public class ColorEvent
{
  public ColorEvent(SolidColorBrush color)
  {
    Color = color;
  }
 
  public SolidColorBrush Color { get; private set; }
}

In order for the Appviewmodel to handle the appropriate events,it will need to implement the IHandle<TMessage> interface.
Appviewmodel中添加事件

public void Handle(ColorEvent message)
{
  Color = message.Color;
}

订阅事件Now we need to subscribe the Appviewmodel to an event aggregator so that it can actually listen to published messages.

[ImportingConstructor]
public Appviewmodel(Colorviewmodel colorModel,IEventAggregator events)
{
  ColorModel = colorModel;
 
  events.Subscribe(this);
}



步骤4:发布

The Colorviewmodel is also going to need the event aggregator so that it can publish messages

private readonly IEventAggregator _events;
 
[ImportingConstructor]
public Colorviewmodel(IEventAggregator events)
{
  _events = events;
}


ColorView

<RadioButton Name="Red" Content="Red" Foreground="White"
             VerticalAlignment="Center" HorizontalAlignment="Center" />
<RadioButton Name="Green" Content="Green" Foreground="White"
             VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Row="1" />
<RadioButton Name="Blue" Content="Blue" Foreground="White"
             VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Row="2" />


Colorviewmodel

public void Red()
{
  _events.Publish(new ColorEvent(new SolidColorBrush(Colors.Red)));
}
 
public void Green()
{
  _events.Publish(new ColorEvent(new SolidColorBrush(Colors.Green)));
}
 
public void Blue()
{
  _events.Publish(new ColorEvent(new SolidColorBrush(Colors.Blue)));
}


http://www.mindscapehq.com/blog/index.php/2012/2/1/caliburn-micro-part-4-the-event-aggregator/

附MEF

1.CompositionContainer

CompositionContainer对象在应用程序中有两种的主要用途。 首先,它跟踪哪些部分可用于组合、它们的依赖项,并且执行可用部分设置的更改组合。其次,它提供了应用程序可以启动组合的方法获取组合部件的实例,或填充可组合部件的依存关系。

部件可直接用于容器,或通过 Catalog 属性来用于容器。在此 ComposablePartCatalog 中可发现的所有部件都可以供容器来满足导入,还包括直接添加的任何部件。

Compose方法允许实例化的部件添加到现有的容器。 假定组合成功,这些部分会在导入中填充从容器检索的部分,导出将可用于其他部分。标记为可重新组合的导入将注册,以进行重新组合。

SatisfyImportsOnce方法允许在不将部件添加到容器的情况下填充该部件的导入部分。 如果组合成功,将填充该部分的导入,但该部分的导出将不能用于其他部分,并且将不为重新组合注册任何导入。

CompositionContainer对象应始终处于释放状态。 调用 Dispose 方法时,CompositionContainer 对象也会释放其创建的所有部件。

使用 CompositionContainer(ComposablePartCatalog,Boolean,ExportProvider[]) 构造函数,可以从多个线程访问的CompositionContainer 对象必须由设置为 trueisThreadSafe 参数构造。 isThreadSafe true性能会稍微变慢,所以我们建议您在单线程的情况下将此参数设置为false 默认值为 false

警告

CompositionContainer永远不导入自身,或导入对其引用的部分。 这种引用可能允许不受信任的一部分获得容器中的所有部分的访问权限。

相关文章

适配器模式将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的类可以相互合作。
策略模式定义了一系列算法族,并封装在类中,它们之间可以互相替换,此模式让算法的变化独立于使用算法...
设计模式讲的是如何编写可扩展、可维护、可读的高质量代码,它是针对软件开发中经常遇到的一些设计问题...
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,使得子类可以在不改变算法结...
迭代器模式提供了一种方法,用于遍历集合对象中的元素,而又不暴露其内部的细节。
外观模式又叫门面模式,它提供了一个统一的(高层)接口,用来访问子系统中的一群接口,使得子系统更容...