使用Unity IoC配置“深度”依赖关系

时间:2011-10-04 12:32:13

标签: c# .net asp.net-mvc asp.net-mvc-2 inversion-of-control

假设我的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-&gt; Service-&gt;存储库并避免在控制器或服务中调用Resolve?

感谢。

2 个答案:

答案 0 :(得分:2)

如果您已经注册了IRepository1-3,那么只需致电{/ p>即可获得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使用无参数构造函数。如果使用public Service()标记构造函数(在本例中为InjectionConstructorAttribute),则可以收到相同的行为。

答案 1 :(得分:0)

肯定只是以下内容 -

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

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