【问题标题】:Issues with IMutableDependencyResolver and Structuremap in ReactiveUIReactiveUI 中 IMutableDependencyResolver 和 Structuremap 的问题
【发布时间】:2014-06-05 19:07:45
【问题描述】:

首先,让我说我不认为这是 ReactiveUI 本身的问题,这就是为什么我没有在其 github repo 上创建问题,其次,我意识到我正在使用ReactiveUI 的测试版。

我想使用 Structuremap,因为我将在我的 WPF 应用程序中有一个插件场景,而 Splat 中的 DI 容器不适合这种事情。

观察这些单元测试:

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

第一个测试通过。第二个测试没有,并提供此堆栈跟踪:

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&lt;RuntimeType&gt; 的视图。任何人都知道为什么会发生这种情况,以及我能做些什么来解决这个问题?我无法使用普通的 Structuremap 配置排除它。

为了清楚起见,这里是解析器和结构映射引导程序的实现:

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

【问题讨论】:

    标签: c# wpf dependency-injection structuremap reactiveui


    【解决方案1】:

    经过一段时间的 ReactiveUI 单元测试,结果是失败的单元测试实际上没有正确实现,应该是这样的:

    [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),而不是实例。

    编辑:我还必须将 with.AddAllTypesOf(typeof (IViewFor&lt;&gt;)); 添加到 Structuremap 配置中。

    【讨论】:

      猜你喜欢
      • 2011-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-05
      相关资源
      最近更新 更多