我正在检查ReactiveUI MVVM框架。我非常喜欢Rx概念,并希望开始使用并为我的下一个项目学习它。
我在尝试将其与Ninject或第三方DI容器一起使用时发现缺少文档。
我通常做的是在平台应用程序层设置Ninject并在那里注册依赖项。然后使用它通过构造函数注入依赖项,或者根据需要通过服务位置解析它们。
我发现这种可选构造函数依赖项的模式非常好,使得构造函数中的依赖项可选,如果null使用服务位置解析,则在单元测试时注入模拟依赖项。
所以,让我们说你有这个构造函数。
public OrdersListViewModel(IWebOrdersRepository<Order> webOrdersRepository = null)
{
_webOrdersRepository = webOrdersRepository ?? Locator.Current.GetService<IWebOrdersRepository<Order>>();
}
这是使用Splat服务定位器,但我想使用Ninject构造函数注入和服务位置。
我在iOS平台项目中做的是以下内容。
public class NinjectConfiguration : NinjectModule
{
public override void Load()
{
BindImplementations ();
}
private void BindImplementations()
{
Bind<IWebOrdersRepository<Order>> ().To<WebOrdersRepository> ().InSingletonScope();
Bind<OrdersListViewModel>().ToSelf();
}
}
在AppDelegate.cs。
NinjectKernel.Initialize(new NinjectConfiguration());
我在UIViewController ViewDidLoad方法中创建一个OrdersListViewModel。
public override async void ViewDidLoad()
{
base.ViewDidLoad();
ViewModel = await BlobCache.LocalMachine.GetOrCreateObject(OrdersListViewModel.Key, () => {
return NinjectKernel.Get<OrdersListViewModel>();
});
}
上面应该创建一个注入依赖项的OrdersListViewModel实例。
运行iOS应用程序不会在构造函数中注入依赖项,因此它始终属于服务位置解析。
我绝对可以在没有DI的情况下实现可选的构造函数模式,因为单元测试仍然很容易,但我想知道为什么它不起作用。
我在此链接https://reactiveui.readthedocs.org/en/latest/dependency-injection/splat/中找到了最后一段说法。
本指南的“高级”部分介绍了如何连接第三方 依赖注入框架。但是,读者很高兴 鼓励放弃这个想法并使用默认的解析器。
但是,无法找到高级部分,为什么鼓励放弃这个想法呢?我仍然可以从世界各地获得最好的,对吗?
此时不太确定是否存在Ninject问题,或者我不知道将其与ReactiveUI联系起来的步骤,尽管我之前没有遇到Ninject DI的问题。
答案 0 :(得分:2)
我很难确切地说出您的解决方案出了什么问题,但我想我可以为您提供一些关于将DI框架连接到RxUI的指示。
您可以找到good example using Autofac on Github。这一切都归结为将您选择的DI包装在实现IMutableDependencyResolver
的类中(请参阅example),然后将其分配给Locator.Current
属性。
至于为什么你最好使用Splat,there is a great answer on SO by the creator of RxUI and Splat himself来讨论这个话题。基本上,
我一般认为围绕IoC / DI的许多建议在“跨平台移动应用程序”领域都非常糟糕,因为你必须记住他们的很多想法都是针对网络应用程序而不是移动应用程序编写的。桌面应用程序。
例如,绝大多数流行的IoC容器只关注热缓存的解析速度,而基本上完全无视内存使用或启动时间 - 这对于服务器应用来说是100%的好,因为这些都无关紧要;但对于移动应用程序?启动时间很长。
Splat的服务位置解决了RxUI的许多问题:
- 服务地点很快,几乎没有设置的开销。
- 它封装了几个不同的常见对象生命周期模型(即“每次创建新的”,“单身”,“懒惰”),只是通过不同的方式编写Func
- Mono Linker友好(一般)
- 服务位置允许我们在特定于平台的代码中注册类型,但在PCL代码中使用它们。
醇>