使用 MediatR、StructureMap、Caliburn.Micro 作为处理程序的 ViewModels [英] ViewModels as Handlers with MediatR, StructureMap, Caliburn.Micro

查看:33
本文介绍了使用 MediatR、StructureMap、Caliburn.Micro 作为处理程序的 ViewModels的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们的 MVVM 框架使用 Caliburn.Micro,IoC 容器使用 StructureMap,中介器实现使用 MediatR.这一切正常,除了推荐的注册 MediatR 事件处理程序的方法与 Caliburn.Micro 推荐的使用 ViewModel 作为它们自己的处理程序的方法不兼容.

We are using Caliburn.Micro for our MVVM framework, StructureMap for our IoC container, and MediatR for our mediator implementation. This is all working fine, except the recommended way to register the MediatR event handlers doesn't play nicely with Caliburn.Micro's recommended approach with using the ViewModels as their own handlers.

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

Caliburn.Micro implements the mediator pattern via the EventAggregator, which requires that you inject the IEventAggregator into your ViewModel and Subscribe to itself (or something implements the IHandle<> interface). MediatR takes a more decoupled approach, recommending you reflectively scan assemblies for types that close the IRequestHandler<,> and other types.

我认为我的问题是缺乏 StructureMap 的经验.

I believe it's my lack of experience with StructureMap that is my issue.

我想做的是能够在 ViewModel 本身上实现处理程序功能(如 Caliburn.Micro 建议的那样),同时确保 ViewModel 注册为 Caliburn.Micro 的单例.

What I'd like to do is be able to implement the Handler functionality on the ViewModels themselves (like Caliburn.Micro suggests) but also ensure the ViewModels are registered as Singletons for Caliburn.Micro.

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

当 StructureMap 处理以下 Registry 时,将有 2 个 RibbonMenuViewModel 实例:一个用于 Caliburn.Micro 的单例版本和一个关闭 MediatR INotificationHandler<> 的瞬态版本.泛型.

When StructureMap processes the following Registry, there will be 2 instances of RibbonMenuViewModel: one singleton version for Caliburn.Micro and one transient version that closes the MediatR INotificationHandler<> generic type.

StructureMap 注册表

StructureMap Registry

    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 实例的最佳方法提供建议

I would like advice on the best way to use the Singleton ViewModel registration as the INotificationHandler instance for MediatR

这里是 Caliburn.Micro 配置供参考:

Here is the Caliburn.Micro configuration for reference:

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

    
    

推荐答案

我遇到了类似的问题.这是我修复它的方法.

I had a similar problem. Here is how I fixed it.

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

    }
}

我希望这会有所帮助.

这篇关于使用 MediatR、StructureMap、Caliburn.Micro 作为处理程序的 ViewModels的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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