ViewModels作为MediatR处理程序,StructureMap,Caliburn.Micro

时间:2016-03-02 23:34:48

标签: structuremap caliburn.micro mediator mediatr

我们使用Caliburn.Micro作为我们的MVVM框架,使用StructureMap作为IoC容器,使用MediatR作为我们的中介实现。这一切都很好,除了注册MediatR事件处理程序的推荐方法与Caliburn.Micro推荐的方法并没有很好地结合使用ViewModels作为他们自己的处理程序。

Caliburn.Micro通过EventAggregator实现中介模式,这需要您将IEventAggregator注入ViewModel并订阅自身(或实现IHandle<>接口的东西)。 MediatR采用更加分离的方法,建议您反射扫描程序集以查找关闭IRequestHandler<,>的类型。和其他类型。

我相信我缺乏结构化的经验,这是我的问题。

我想要做的是能够在ViewModel上实现Handler功能(如Caliburn.Micro建议),但也要确保ViewModel注册为Caliburn.Micro的Singletons。

    public class RibbonMenuViewModel : PropertyChangedBase, INotificationHandler<SomethingSelectedEvent> { }

当StructureMap处理以下注册表时,将有2个RibbonMenuViewModel实例:一个用于Caliburn.Micro的单例版本和一个关闭MediatR INotificationHandler&lt;&gt;的瞬态版本。通用类型。

StructureMap注册表

    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 Bootstrapper配置

    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); }

1 个答案:

答案 0 :(得分:0)

我有类似的问题。 以下是我修复它的方法。

public class ViewModelsRegistry : Registry
{
    public ViewModelsRegistry()
    {

        // 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<>));
            s.ExcludeType<RibbonMenuViewModel>();
        });
        // ensure registration for the ViewModel for Caliburn.Micro         

        For(typeof(INotificationHandler<>)).Singleton().Add(typeof(RibbonMenuViewModel));

    }
}

我希望这会有所帮助。