Как внедрить фабрику универсальных типов с помощью Autofac

Имею репозиторий factory NhRepositoryFactory

public interface IRepositoryFactory  
{  
  IRepository<T> Create<T>() where T: Entity;  
} 

public class NhRepositoryFactory: IRepositoryFactory  
{  
  public IRepository<T> Create<T>() where T : Entity  
  {  
    return new NhRepository<T>();  
  }  
}

Чтобы разрешить некоторые зависимости репозиториев, я хочу получить их из контейнера Autofac. Так что я должен каким-то образом внедрить Func<IRepository<T>> factory в свой класс. Как я могу это сделать?
Заранее спасибо.


person Dmitriy Melnik    schedule 12.03.2012    source источник
comment
Почему бы вам не хранить контейнер Autofac внутри NhRepositoryFactory?   -  person Steven    schedule 12.03.2012
comment
Я хочу, чтобы моя фабрика была независимой от Autofac.   -  person Dmitriy Melnik    schedule 12.03.2012
comment
Он содержит всего одну строчку кода. Вы можете поместить его в корень вашей композиции. Он не должен быть независимым от контейнера.   -  person Steven    schedule 12.03.2012
comment
Я не понимаю. IRepositoryFactory также решается с помощью Autofac. Не могли бы вы написать, как будет выглядеть метод Create?   -  person Dmitriy Melnik    schedule 12.03.2012
comment
Ваш вопрос похож на stackoverflow .com / questions / 8579128 /, и вот ответ.   -  person rcaval    schedule 12.03.2012


Ответы (2)


NhRepositoryFactory не содержит бизнес-логики и может быть частью корня вашей композиции. Это позволяет вам дать ему ссылку на контейнер. Это просто механика и не считается шаблон. NhRepositoryFactory будет выглядеть так:

// This class is part of your composition root
public class NhRepositoryFactory : IRepositoryFactory  
{
    private readonly Container container;

    public NhRepositoryFactory(Container container)
    {
        this.container = container;
    }

    public IRepository<T> Create<T>() where T : Entity  
    {  
        return this.container.Resolve<NhRepository<T>>();
    }  
}

А зарегистрировать это можно так:

builder.Register<IService>(c => new NhRepositoryFactory(c))
    .SingleInstance();
person Steven    schedule 12.03.2012
comment
Я согласен, что так или иначе соединение с Autofac кажется неизбежным. Я сделал это так, как вы предложили. Разница в том, что я пропустил ILifetimeScope вместо Container. - person Dmitriy Melnik; 12.03.2012
comment
Я изменил реализацию. Я создал IObjectFactory интерфейс с T Create<T>() методом, который использует ILifetimeScope для создания объектов. Это реализуется классом AutofacObjectFactory, который вводится в NhRepositoryFactory. Так что теперь Autofac-сцепления нет. - person Dmitriy Melnik; 13.03.2012
comment
После рефакторинга IRepositoryFactory был исключен. Его место занял IObjectFactory. - person Dmitriy Melnik; 13.03.2012
comment
Я считаю, что это просто плохая практика. Почему вы возвращаете NhRepository из factory, а не вводите его через инъекцию конструктора? Заводской узор здесь не имеет смысла. - person Sergey Akopov; 29.11.2012
comment
@DmitriyMelnik Могу я спросить последний пример? - person Akim Khalilov; 28.12.2012

Autofac также может обрабатывать общее создание без использования фабрики.

builder.RegisterGeneric(typeof(NhRepository<>))
    .As(typeof(IRepository<>))
    .InstancePerLifetimeScope();

Используя этот шаблон, вы можете просто установить зависимость от IRepository, и autofac заполнит зависимости.

person Danielg    schedule 12.03.2012
comment
Я пробовал вот так. Но когда какому-то классу требовалось несколько репозиториев, мне приходилось добавлять их в качестве параметров конструктора. Также должно было быть создано поле для каждого из них. Это казалось неуклюжим, поэтому я создал фабрику. - person Dmitriy Melnik; 13.03.2012