ReactiveUI中的IMutableDependencyResolver和Structuremap问题 [英] Issues with IMutableDependencyResolver and Structuremap in ReactiveUI

查看:64
本文介绍了ReactiveUI中的IMutableDependencyResolver和Structuremap问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我要说的是,我认为这并不是ReactiveUI本身的问题,这就是为什么我没有在github存储库上创建问题的原因,其次,我意识到我正在使用

First off, let me say that I don't think that is is an issue with ReactiveUI per se, which is why I've not created an issue on its github repo, and second, I realise that I'm using a beta version of ReactiveUI.

我想使用Structuremap,因为我要在WPF应用程序中使用插件方案,而Splat中的DI容器不是

I want to use Structuremap because I'm going to have a plugin scenario in my WPF app, and the DI container in Splat isn't cut out for that sort of thing.

观察以下单元测试:

[Fact]
public void ShouldBeAbleToOverrideDefaultDependencyResolver()
{
    Locator.Current = new ApplicationDependencyResolver(StructureMapBootstrapper.Instance.Container);
    Locator.CurrentMutable.InitializeSplat();
    Locator.CurrentMutable.InitializeReactiveUI();

    var view = Locator.Current.GetService<SplashScreenView>();

    view.Should().NotBeNull().And.BeOfType<SplashScreenView>();
}

[Fact]
public void ShouldBeAbleToLocateTheViewForAViewModel()
{
    Locator.Current = new ApplicationDependencyResolver(StructureMapBootstrapper.Instance.Container);
    Locator.CurrentMutable.InitializeSplat();
    Locator.CurrentMutable.InitializeReactiveUI();
    var viewLocator = Locator.Current.GetService<IViewLocator>();

    var view = viewLocator.ResolveView(typeof (SplashScreenViewModel));

    view.Should().NotBeNull().And.BeOfType<SplashScreenView>();
}

第一次测试通过。第二个测试没有,并且提供了以下堆栈跟踪:

The first test passes. The second test does not, and provides this stacktrace:

StructureMap.StructureMapConfigurationExceptionNo default Instance is registered and cannot be automatically determined for type 'IViewFor<RuntimeType>'

There is no configuration specified for IViewFor<RuntimeType>

1.) Container.GetInstance(IViewFor<RuntimeType>)

   at StructureMap.SessionCache.GetDefault(Type pluginType, IPipelineGraph pipelineGraph) in c:\BuildAgent\work\996e173a8ceccdca\src\StructureMap\SessionCache.cs: line 63
   at StructureMap.Container.GetInstance(Type pluginType) in c:\BuildAgent\work\996e173a8ceccdca\src\StructureMap\Container.cs: line 325
   at Redacted.ApplicationDependencyResolver.GetService(Type serviceType, String contract) in ApplicationDependencyResolver.cs: line 27
   at ReactiveUI.DefaultViewLocator.attemptToResolveView(Type type, String contract)
   at ReactiveUI.DefaultViewLocator.ResolveView(T viewModel, String contract)
   at Redacted.BootstrapAndDependencyResolutionTests.ShouldBeAbleToLocateTheViewForAViewModel() in BootstrapAndDependencyResolutionTests.cs: line 39

我显然没有,也不能拥有实现 IViewFor< RuntimeType>的任何视图; 。任何人都知道为什么会发生这种情况,而我能做些什么来解决这个问题?我不能使用正常的Structuremap配置来排除它。

I obviously do not, and can not, have any views which implement IViewFor<RuntimeType>. Anyone got any ideas as to why this is happening, and what I can do to get around this? I can't exclude it using the normal Structuremap configuration.

为清楚起见,这里是解析器和structuremap引导程序的实现:

For full clarity here are the implementations of the resolver and the structuremap bootstrapper:

    public class ApplicationDependencyResolver : IMutableDependencyResolver
{
    private readonly IContainer _container;

    public ApplicationDependencyResolver(IContainer container)
    {
        _container = container;
    }

    public void Dispose()
    {
        _container.Dispose();
    }

    public object GetService(Type serviceType, string contract = null)
    {
        return string.IsNullOrEmpty(contract)
            ? _container.GetInstance(serviceType)
            : _container.GetInstance(serviceType, contract);
    }

    public IEnumerable<object> GetServices(Type serviceType, string contract = null)
    {
        return _container.GetAllInstances(serviceType).Cast<object>();
    }

    public void Register(Func<object> factory, Type serviceType, string contract = null)
    {
        var o = factory();
        _container.Configure(configure => configure.For(serviceType).Use(o));
    }
}

    public sealed class StructureMapBootstrapper
{
    private static readonly StructureMapBootstrapper InternalInstance = new StructureMapBootstrapper();

    static StructureMapBootstrapper() { }

    private StructureMapBootstrapper()
    {
        Configure();
    }

    public static StructureMapBootstrapper Instance { get { return InternalInstance; } }

    public IContainer Container { get; private set; }

    private void Configure()
    {
        Container = new Container(configure =>
        {
            configure.Scan(with =>
            {
                with.TheCallingAssembly();
                with.LookForRegistries();
                with.WithDefaultConventions();
            });
        });
    }
}


推荐答案

之后使用ReactiveUI单元测试花费了一些时间,事实证明失败的单元测试实际上没有正确实现,应该看起来像这样:

After some quality time with the ReactiveUI unit tests, it turns out that the unit test which was failing was actually not implemented correctly, and should look like this:

[Fact]
public void ShouldBeAbleToLocateTheViewForAViewModel()
{
    var container = StructureMapBootstrapper.Instance.Container;
    var ihas = container.WhatDoIHave();
    Locator.Current = new ApplicationDependencyResolver(container);
    Locator.CurrentMutable.InitializeSplat();
    Locator.CurrentMutable.InitializeReactiveUI();
    var vm = new SplashScreenViewModel();

    var viewLocator = Locator.Current.GetService<IViewLocator>();

    var view = viewLocator.ResolveView(vm);

    view.Should().NotBeNull().And.BeOfType<SplashScreenView>();
}

具体来说,这是我通过了 typeof的事实(SplashScreenViewMode)(而不是实例)导致测试失败。

Specifically, it was the fact I was passing typeof(SplashScreenViewMode), and not an instance, that was causing the test to fail.

编辑:我还必须添加 with.AddAllTypesOf(typeof(IViewFor<>))); 到Structuremap配置。

I also had to add with.AddAllTypesOf(typeof (IViewFor<>)); to the Structuremap configuration.

这篇关于ReactiveUI中的IMutableDependencyResolver和Structuremap问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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