我们将 Caliburn.Micro 用于我们的 MVVM 框架,将 StructureMap 用于我们的 IoC 容器,并将 MediatR 用于我们的中介器实现。这一切都很好,除了注册 MediatR 事件处理程序的推荐方法与 Caliburn.Micro 推荐的使用 ViewModels 作为它们自己的处理程序的方法不能很好地配合。
Caliburn.Micro 通过 EventAggregator 实现中介者模式,这要求您将 IEventAggregator 注入 ViewModel 并订阅自身(或实现 IHandle<> 接口的东西)。MediatR 采用更加解耦的方法,建议您反射性地扫描程序集以查找关闭 IRequestHandler<,> 和其他类型的类型。
我相信我缺乏使用 StructureMap 的经验是我的问题。
我想做的是能够在 ViewModel 本身上实现 Handler 功能(如 Caliburn.Micro 建议的那样),但也确保 ViewModel 被注册为 Caliburn.Micro 的 Singletons。
public class RibbonMenuViewModel : PropertyChangedBase, INotificationHandler<SomethingSelectedEvent> { }
当 StructureMap 处理以下注册表时,将有 2 个 RibbonMenuViewModel 实例:一个用于 Caliburn.Micro 的单例版本和一个关闭 MediatR INotificationHandler<> 泛型类型的临时版本。
结构图注册表
public class ViewModelsRegistry : Registry
{
public ViewModelsRegistry()
{
// ensure registration for the ViewModel for Caliburn.Micro
this.ForConcreteType<RibbonMenuViewModel>().Configure.Singleton();
// MediatR handler registrations
this.Scan(s =>
{
s.Assembly(this.GetType().Assembly);
s.ConnectImplementationsToTypesClosing(typeof (IRequestHandler<,>));
s.ConnectImplementationsToTypesClosing(typeof (IAsyncRequestHandler<,>));
s.ConnectImplementationsToTypesClosing(typeof (INotificationHandler<>));
s.ConnectImplementationsToTypesClosing(typeof (IAsyncNotificationHandler<>));
});
}
}
我想就使用 Singleton ViewModel 注册作为 MediatR 的 INotificationHandler 实例的最佳方法提出建议
这是 Caliburn.Micro 配置供参考:
Caliburn 引导程序配置
protected override void Configure()
{
this.configureTypeMappings();
if (!Execute.InDesignMode)
{
this.configureIocContainer();
}
}
private void configureIocContainer()
{
this.container = new Container(this.getStructureMapConfig);
}
private void getStructureMapConfig(ConfigurationExpression cfg)
{
cfg.For<IWindowManager>().Use<WindowManager>().Singleton();
cfg.Scan(s =>
{
s.AssemblyContainingType<ViewModelsRegistry>();
s.LookForRegistries();
});
}
protected override IEnumerable<object> GetAllInstances(Type serviceType)
{
return this.container.GetAllInstances(serviceType).OfType<object>();
}
protected override object GetInstance(Type serviceType, string key)
{
if (serviceType == null) serviceType = typeof(object);
var returnValue = key == null
? this.container.GetInstance(serviceType) : this.container.GetInstance(serviceType, key);
return returnValue;
}
protected override void BuildUp(object instance) { this.container.BuildUp(instance); }