在我最近使用的MVC应用程序中,他们已经注册并解决了控制器内部的所有接口/混凝土类依赖关系。我读了关于ioc和依赖反转的文章,发现已经做的事情完全没有用处。由于它无论如何都不允许应用程序利用IoC示例模拟、单元测试的好处,而且还会不必要地增加添加/解决依赖关系的成本。以下是代码示例:
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");