2

我们将 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); }

    
    
4

1 回答 1

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

    }
}

我希望这有帮助。

于 2016-03-11T09:41:32.777 回答