Настройка «глубоких» зависимостей с Unity IoC - PullRequest
3 голосов
/ 04 октября 2011

Допустим, в моем проекте 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 внутри контроллеров или служб?

Спасибо.

Ответы [ 2 ]

2 голосов
/ 04 октября 2011

Если вы уже зарегистрировали 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 использовать конструктор без параметров.Такое же поведение можно получить, если пометить конструктор (в данном случае public Service()) с помощью InjectionConstructorAttribute.

0 голосов
/ 04 октября 2011

точно только следующее -

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

и то же самое для Service2. Контейнер IoC создаст объекты для вас

...