使用统一容器添加、解决控制器本身的依赖关系有什么实际用途吗?
Is there any practical usage of using unity container to add, resolve dependencies in the controller itself?
在我最近使用的 MVC 应用程序中,他们已经注册并解析了控制器本身内部的所有 Interface/Concrete class 依赖项。看了ioc和dependency inversion,发现做的东西完全没用。因为它无论如何都不允许应用程序利用 IoC 示例模拟、单元测试的好处,并且还会不必要地增加 adding/resolving 依赖项的成本。下面是代码示例:
HomeController
using(IUnityContainer container= new UnityContainer())
{
container.RegisterType<IRepository1, Repository1>()
IRepository1 _repos1 = container.Resolve<IRepository1>();
}
如果我们没有从中得到任何好处,我认为做所有这些事情没有任何意义。有人可以告诉我这现在或将来是否有用吗?
如果没有,我打算用具体的实现或类似的方式简单地实例化它们:
IRepository1 repos1= new Repository1();
请忽略语法。
(我现在已经编辑了代码片段。)
使用容器首先注册然后解析具体类型没有任何意义,没有任何好处。你仍然耦合到一个具体的类型。您可能会争辩说容器有助于将所有构造函数参数与相应类型的实例相匹配,但在我看来这不算是真正的好处。
如果您真的不打算使用在外部解析的抽象,那么是的,您可以安全地删除膨胀的容器代码并创建具体的实例,就像您介绍的那样。
这个问题的直接答案是你当前的实现比标准构造造成更多的开销和性能影响,你应该删除它;或重新设计您的 Unity 实现。
以下示例说明了在解析为依赖于已注册到统一容器的另一种类型的类型时注入的好处。
public class UserService
{
internal readonly IRepository _repository;
public UserService(IRepository repository)
{
_repository = repository;
}
//Service Method that exposes 'Domain Logic'
public void CreateUser(string FirstName)
{
_repository.Insert<User>(new User() { FirstName = FirstName }); //Assumes there is a Generic method, Insert<T>, that attaches instances to the underline context.
}
public User GetUser(string FirstName)
{
return _repository.Query<User>().FirstOrDefault(user => user.FirstName == FirstName); // assumes there is a Generic method, Query<T>, that returns IQueryable<T> on IRepository
}
}
注册类型(可能在 Global.asax 的单例模式中)
//Resolver is an instance of UnityContainer
Resolver.RegisterType<IRepository, Repository>(new ContainerControlledLifetimeManager());
Resolver.RegisterType<IUserService, UserService>();
那么你控制器中的逻辑是这样的:
var service = Resolver.Resolve<IUserService>(); //the resolver will resolve IRepository to an instance as well...
var user = service.GetUser("Grant");
在我最近使用的 MVC 应用程序中,他们已经注册并解析了控制器本身内部的所有 Interface/Concrete class 依赖项。看了ioc和dependency inversion,发现做的东西完全没用。因为它无论如何都不允许应用程序利用 IoC 示例模拟、单元测试的好处,并且还会不必要地增加 adding/resolving 依赖项的成本。下面是代码示例:
HomeController
using(IUnityContainer container= new UnityContainer())
{
container.RegisterType<IRepository1, Repository1>()
IRepository1 _repos1 = container.Resolve<IRepository1>();
}
如果我们没有从中得到任何好处,我认为做所有这些事情没有任何意义。有人可以告诉我这现在或将来是否有用吗?
如果没有,我打算用具体的实现或类似的方式简单地实例化它们:
IRepository1 repos1= new Repository1();
请忽略语法。
(我现在已经编辑了代码片段。)
使用容器首先注册然后解析具体类型没有任何意义,没有任何好处。你仍然耦合到一个具体的类型。您可能会争辩说容器有助于将所有构造函数参数与相应类型的实例相匹配,但在我看来这不算是真正的好处。
如果您真的不打算使用在外部解析的抽象,那么是的,您可以安全地删除膨胀的容器代码并创建具体的实例,就像您介绍的那样。
这个问题的直接答案是你当前的实现比标准构造造成更多的开销和性能影响,你应该删除它;或重新设计您的 Unity 实现。
以下示例说明了在解析为依赖于已注册到统一容器的另一种类型的类型时注入的好处。
public class UserService
{
internal readonly IRepository _repository;
public UserService(IRepository repository)
{
_repository = repository;
}
//Service Method that exposes 'Domain Logic'
public void CreateUser(string FirstName)
{
_repository.Insert<User>(new User() { FirstName = FirstName }); //Assumes there is a Generic method, Insert<T>, that attaches instances to the underline context.
}
public User GetUser(string FirstName)
{
return _repository.Query<User>().FirstOrDefault(user => user.FirstName == FirstName); // assumes there is a Generic method, Query<T>, that returns IQueryable<T> on IRepository
}
}
注册类型(可能在 Global.asax 的单例模式中)
//Resolver is an instance of UnityContainer
Resolver.RegisterType<IRepository, Repository>(new ContainerControlledLifetimeManager());
Resolver.RegisterType<IUserService, UserService>();
那么你控制器中的逻辑是这样的:
var service = Resolver.Resolve<IUserService>(); //the resolver will resolve IRepository to an instance as well...
var user = service.GetUser("Grant");