问题描述
首先,我要说的是,我认为这并不是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问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!