配置& # 39;深# 39;依赖于Unity的IoC

本文关键字:IoC Unity 依赖于 配置 | 更新日期: 2023-09-27 18:10:34

假设我在MVC 2项目中有以下类和接口:

存储库:

IRepository1, IRepository2, IRepository3

public class ConcreteRepository1 : IRepository1
{
     public ConcreteRepository1()
     {
         ...
     }
     ...
}
public class ConcreteRepository2 : IRepository2
{
     public ConcreteRepository2()
     {
         ...
     }
     ...
}
public class ConcreteRepository3 : IRepository3
{
     public ConcreteRepository3()
     {
         ...
     }
     ...
}
服务类:

public class Service1
{
    private IRepository1 repo1;
    private IRepository2 repo2;
    public Service1(IRepository1 repo1, IRepository2 repo2)
    {
        this.repo1 = repo1;
        this.repo2 = repo2;
    }
    ...
}

控制器:

public class Controller1 : Controller
{
    private Service1 srv1;
    private Service2 srv2;
    public Controller1(Service1 srv1, Service2 srv2)
    {
        this.srv1 = srv1;
        this.srv2 = srv2;
    }
    ...
}

我有自定义的ControllerFactory,我知道如何将具体的存储库绑定到接口:

IUnityContainer container = new UnityContainer();
container.RegisterType<IRepository1, ConcreteRepository1>(new TransientLifetimeManager(), new InjectionConstructor());
container.RegisterType<IRepository2, ConcreteRepository2>(new TransientLifetimeManager(), new InjectionConstructor());
container.RegisterType<IRepository3, ConcreteRepository3>(new TransientLifetimeManager(), new InjectionConstructor());

问题是我应该如何在我的自定义ControllerFactory中注册服务的实例和控制器的类型,以使统一容器解析整个层次结构Controller->Service->Repository,并避免在控制器或服务中调用resolve ?

谢谢。

配置& # 39;深# 39;依赖于Unity的IoC

如果您已经注册了IRepository1-3,那么您可以简单地调用

获得Service1实例
container.Resolve<Service1>()

调用container.Resolve<Controller1>()将自动解析依赖关系并创建类型为Controller1的实例。

示例:

public interface IRepository1 { }
public interface IRepository2 { }
public interface IRepository3 { }
public class ConcreteRepository1 : IRepository1 { }
public class ConcreteRepository2 : IRepository2 { }
public class ConcreteRepository3 : IRepository3 { }
public class Service1
{
    private IRepository1 repo1;
    private IRepository2 repo2;
    public Service1(IRepository1 repo1, IRepository2 repo2)
    {
        this.repo1 = repo1;
        this.repo2 = repo2;
    }
}
public class Service2
{
    private IRepository1 repo1;
    private IRepository2 repo2;
    public Service2(IRepository1 repo1, IRepository3 repo3)
    {
        this.repo1 = repo1;
        this.repo2 = repo2;
    }
}
public class Controller1
{
    private Service1 srv1;
    private Service2 srv2;
    public Controller1(Service1 srv1, Service2 srv2)
    {
        this.srv1 = srv1;
        this.srv2 = srv2;
    }
}
解决:

var container = new UnityContainer();
container.RegisterType<IRepository1, ConcreteRepository1>();
container.RegisterType<IRepository2, ConcreteRepository2>();
container.RegisterType<IRepository3, ConcreteRepository3>();
var controller = container.Resolve<Controller1>();

编辑:

public interface IRepository { }
public class Repository : IRepository { }
public class Service
{
    //[InjectionConstructor]
    public Service()
    {
        Console.WriteLine("Parameterless constructor called");
    }
    public Service(IRepository repository)
    {
        Console.WriteLine("Contructor with IRepository called");
    }
}
private static void Main()
{
    var container = new UnityContainer();
    container.RegisterType<IRepository, Repository>();
    var service = container.Resolve<Service>();
    container.RegisterType<Service>(new InjectionConstructor());
    var service2 = container.Resolve<Service>();
}
输出:

Contructor with IRepository called
Parameterless constructor called

所以,当我们没有注册Service时(换句话说,它有默认的解析行为),Unity默认使用最贪婪的构造函数构建Service。当你指定new InjectionConstructor()时,这告诉Unity使用无参数构造函数。如果您用InjectionConstructorAttribute标记构造函数(在本例中为public Service()),则可以收到相同的行为。

当然是以下-

container.RegisterType<Service1>(new TransientLifetimeManager(), new InjectionConstructor());

Service2相同。IoC容器将为您构造对象