使用IUnityContainer作为构造函数参数的不良做法?备择方案?

时间:2022-12-29 00:02:09

I asked myself if it is a bad practice to use a DI Container in the constructor of an implemented class like this:

我问自己,在这样实现的类的构造函数中使用DI容器是否是一种不好的做法:

public LoginViewModel( IUnityContainer unityContainer ) { //... }

If so ... what is a good workaround if I have more than 5 params I need to pass? Redesign? When is it 'allowed' to use the Container?

如果是这样的话......如果我有超过5个参数,我需要通过什么是一个好的解决方法?重新设计?什么时候“允许”使用容器?

What about the principles in .NET PRISM ? While loading a module I sometimes have to register specific classes inside a Module but this is against the composition root principle isn't it?

.NET PRISM的原理怎么样?在加载模块时,我有时必须在模块内注册特定的类,但这是违反组合根本原则的不是吗?

2 个解决方案

#1


2  

Generally, it is bad practise to inject the container into the viewmodel, simply because, it shouldn't be necessary. This blog post summarises the reasons quite concisely: MVVM anti-pattern: Injecting the IoC container into a View Model

通常,将容器注入视图模型是不好的做法,因为它不应该是必需的。这篇博文简明扼要地总结了原因:MVVM反模式:将IoC容器注入视图模型

The view model itself doesn't decide what classes (interfaces) it needs to use. It has a defined job, it receives its dependencies (defined in the constructor) and works with them. If it has a lot of dependencies, I would start to think, am I violating the purpose of this view model, that is, is it still SOLID. I look through all the dependencies and if the work being done is justified, then fine. If not, then I break it out in an appropriate fashion.

视图模型本身并不决定它需要使用哪些类(接口)。它有一个已定义的作业,它接收它的依赖项(在构造函数中定义)并使用它们。如果它有很多依赖关系,我会开始思考,我是否违反了这个视图模型的目的,就是它仍然是SOLID。我查看所有依赖项,如果正在完成的工作是合理的,那么很好。如果没有,那么我以适当的方式将其分解。

For your modules, in your bootstrapper you register all your modules in one location (for Unity, by overriding the ConfigureModuleCatalog method). Each module will be required to register its own components with the container so it is perfectly valid for the module to receive the container. It is only when the ConfigureModuleCatalog is executed at application startup, that the entire object graph is finally composed. This is what the composition root pattern is all about.

对于您的模块,在您的引导程序中,您将所有模块注册到一个位置(对于Unity,通过重写ConfigureModuleCatalog方法)。每个模块都需要在容器中注册自己的组件,这样模块才能完全有效地接收容器。只有在应用程序启动时执行ConfigureModuleCatalog时,才会最终组成整个对象图。这就是组合根模式的全部内容。

#2


2  

Sure, you can do this, but than has your LoginViewModel a direct dependency to the Unity container (Framework) and normally you want to avoid this. This also makes it hard to test your LoginViewModel, cause you need to instantiate (or mock) the Container in your tests.

当然,你可以这样做,但是你的LoginViewModel直接依赖于Unity容器(Framework),通常你想避免这种情况。这也使您很难测试您的LoginViewModel,因为您需要在测试中实例化(或模拟)Container。

Also if you want to switch your DI Framework you need to change your class.

此外,如果您想切换DI框架,则需要更改课程。

Best practice for class design and dependency injection is to inject all required dependencies via constructor and optional dependencies via properties. For the optional dependencies your class could set a default implementation in the constructor.

类设计和依赖注入的最佳实践是通过构造函数和可选的依赖项通过属性注入所有必需的依赖项。对于可选的依赖项,您的类可以在构造函数中设置默认实现。

Without further knowledge about your class design it is hard so say if you need to refactor or redesign your class, but it smells that your LoginViewModel has more responsibility than it should have.

如果你没有进一步了解你的课堂设计,那么你很难说你需要重构或重新设计你的课程,但它会让你觉得你的LoginViewModel有更多的责任。

I have used PRISM in my last application I worked on and for Modules, that need to register additional types in the container for DI, it is totally fine to pass an instance of the UnityContainer to.

我在上一个应用程序和模块中使用了PRISM,需要在容器中为DI注册其他类型,将UnityContainer的实例传递给它是完全没问题的。

#1


2  

Generally, it is bad practise to inject the container into the viewmodel, simply because, it shouldn't be necessary. This blog post summarises the reasons quite concisely: MVVM anti-pattern: Injecting the IoC container into a View Model

通常,将容器注入视图模型是不好的做法,因为它不应该是必需的。这篇博文简明扼要地总结了原因:MVVM反模式:将IoC容器注入视图模型

The view model itself doesn't decide what classes (interfaces) it needs to use. It has a defined job, it receives its dependencies (defined in the constructor) and works with them. If it has a lot of dependencies, I would start to think, am I violating the purpose of this view model, that is, is it still SOLID. I look through all the dependencies and if the work being done is justified, then fine. If not, then I break it out in an appropriate fashion.

视图模型本身并不决定它需要使用哪些类(接口)。它有一个已定义的作业,它接收它的依赖项(在构造函数中定义)并使用它们。如果它有很多依赖关系,我会开始思考,我是否违反了这个视图模型的目的,就是它仍然是SOLID。我查看所有依赖项,如果正在完成的工作是合理的,那么很好。如果没有,那么我以适当的方式将其分解。

For your modules, in your bootstrapper you register all your modules in one location (for Unity, by overriding the ConfigureModuleCatalog method). Each module will be required to register its own components with the container so it is perfectly valid for the module to receive the container. It is only when the ConfigureModuleCatalog is executed at application startup, that the entire object graph is finally composed. This is what the composition root pattern is all about.

对于您的模块,在您的引导程序中,您将所有模块注册到一个位置(对于Unity,通过重写ConfigureModuleCatalog方法)。每个模块都需要在容器中注册自己的组件,这样模块才能完全有效地接收容器。只有在应用程序启动时执行ConfigureModuleCatalog时,才会最终组成整个对象图。这就是组合根模式的全部内容。

#2


2  

Sure, you can do this, but than has your LoginViewModel a direct dependency to the Unity container (Framework) and normally you want to avoid this. This also makes it hard to test your LoginViewModel, cause you need to instantiate (or mock) the Container in your tests.

当然,你可以这样做,但是你的LoginViewModel直接依赖于Unity容器(Framework),通常你想避免这种情况。这也使您很难测试您的LoginViewModel,因为您需要在测试中实例化(或模拟)Container。

Also if you want to switch your DI Framework you need to change your class.

此外,如果您想切换DI框架,则需要更改课程。

Best practice for class design and dependency injection is to inject all required dependencies via constructor and optional dependencies via properties. For the optional dependencies your class could set a default implementation in the constructor.

类设计和依赖注入的最佳实践是通过构造函数和可选的依赖项通过属性注入所有必需的依赖项。对于可选的依赖项,您的类可以在构造函数中设置默认实现。

Without further knowledge about your class design it is hard so say if you need to refactor or redesign your class, but it smells that your LoginViewModel has more responsibility than it should have.

如果你没有进一步了解你的课堂设计,那么你很难说你需要重构或重新设计你的课程,但它会让你觉得你的LoginViewModel有更多的责任。

I have used PRISM in my last application I worked on and for Modules, that need to register additional types in the container for DI, it is totally fine to pass an instance of the UnityContainer to.

我在上一个应用程序和模块中使用了PRISM,需要在容器中为DI注册其他类型,将UnityContainer的实例传递给它是完全没问题的。