使用 Swinject 将 ViewModel 条件注入 ViewController
Posted
技术标签:
【中文标题】使用 Swinject 将 ViewModel 条件注入 ViewController【英文标题】:Conditional injection of ViewModel into ViewController using Swinject 【发布时间】:2017-03-22 12:10:33 【问题描述】:我正在使用Swinject
注入依赖项,到目前为止它运行良好。但是现在我有一个场景,我有一个ViewController
,它依赖于它的ViewModel
。 ViewModel
符合 ViewModeling
协议,并且可以是两种类型之一(两者都符合相同的协议,但具有截然不同的行为)。
我试图弄清楚我怎样才能注入正确的ViewModel
(必须在运行时做出决定)?
我注意到我可以使用Container
通过name
注册每个ViewModel
,然后使用name
来区分应该注入哪个ViewModel
,这乍一看似乎不错解决方案 - 直到我发现我无法使用名称实例化 ViewController
(或者我可能错过了它?)
我还考虑过在我的 DependencyInjector
类上公开一个属性,该属性将用于手动注入正确的 ViewModel
- 尽管我觉得这种方法完全错过了自动依赖注入解决方案的意义,并且还强迫我用一些业务逻辑代码弄脏依赖注入器。
任何帮助或想法将不胜感激。
【问题讨论】:
您是否将 SwinjectStoryboard 用于视图控制器?如果是这样,您可以在情节提要中使用swinjectRegistrationName
属性:github.com/Swinject/SwinjectStoryboard#registration-with-name
我正在使用SwinjectStoryboard
,但您的建议意味着我必须保留两个重复的ViewController
s,并且每个都有不同的名称 - 这对我来说似乎是一个问题(每次更改在ViewController
中意味着我必须记住更新两个副本)
【参考方案1】:
不将 DI 与应用程序逻辑混合的一种方法是使用某种“代理”视图模型,该模型将实现用于区分两种变体的逻辑。您可以使用不同的接口来实现它,例如
protocol ViewModelProxy
var viewModel: ViewModel get
或更透明地:
protocol ViewModel
func foo()
class ViewModelProxy: ViewModel
private let viewModel1: ViewModel
private let viewModel2: ViewModel
private var viewModel: ViewModel
if shouldUseViewModel1
return viewModel1
else
return viewModel2
func foo()
viewModel.foo()
那么你总是可以将ViewModelProxy
注入到视图控制器中。
【讨论】:
以上是关于使用 Swinject 将 ViewModel 条件注入 ViewController的主要内容,如果未能解决你的问题,请参考以下文章
如何将正确的 viewModel 注入单个 viewController
Swinject:如何将委托模式与接口隔离(类与接口)一起使用?