Введя правильный тип в мой бизнес-класс с помощью Autofac

В настоящее время у меня есть бизнес-класс, конструктор которого принимает реализацию репозитория. Существует несколько реализаций этого хранилища. Во время выполнения я хочу решить, какая реализация репозитория должна быть предоставлена. Я новичок в использовании DI-фреймворков, а также Autofac. Вот мои реализации репозитория.

public interface IRepository
{
  string GetData();
}

public class ServiceRepository : IRepository
{
  ///implementation..
}

public class DatabaseRepository : IRepository
{
  ///implementation..
}



public class BusinessClass
{
   public BusinessClass(IRepository repo)
   {
     //assign to local variable
   }
}

Как видите, IRepository имеет несколько реализаций. Однако я хотел бы во время выполнения решить, какой из них следует передать моему бизнес-классу. Я рассмотрел эти примеры здесь и здесь, но, похоже, они не объясняют, как выполнить это требование. Смена дизайна интерфейса на данный момент не вариант. Мне все еще нужно реализовать factoryclass для выборочного разрешения правильного типа?

2 ответа

Вы можете использовать фабричный шаблон здесь, но вам не нужно создавать отдельный фабричный класс, вам будет достаточно Func. Ваш бизнес-уровень не должен знать об этой логике переключения, он должен перейти к контроллеру прикладного уровня.

Один из возможных примеров:

Ваш контроллер

public void SomeController(Func<string, IBusinessService> serviceFactory)
{
    this.serviceFactory = serviceFactory;
}
...
//somewhere inside controller
serviceFactory("database").SomeBusinessLogic();
...

и Autofac регистрация:

builder
.RegisterType<ServiceRepository>()
.Named<IRepository("service");

builder
.RegisterType<DatabaseRepository>()
.Named<IRepository>("database");

builder
.Register<Func<string,IBusinessService>>(cx =>
{
    var componentContext = cx.Resolve<IComponentContext>();
    return (key =>
        new BusinessService(componentContex.ResolveNamed<IRepository>(key))
    );
}
)
.As<Func<string, IBusinessService>>();

Есть несколько более чистых способов сделать это, чем использовать фабрику.

  • Вы можете использовать шаблон "Цепочка ответственности", где вы разрешаете все IRepositories с помощью Autofac, и тогда каждый репозиторий может сообщить вам, несут ли они ответственность за обработку этого запроса.
  • Вы можете включить это в голову и сказать, что у меня есть список репозиториев, мне нужен сервис, который берет эти репозитории и возвращает одно конкретное в зависимости от набора бизнес-правил (по сути, фабрика). Хотя этот подход делает решение немного дружественным к юнит-тестам.

Просто некоторые варианты для вас, чтобы рассмотреть:)

Другие вопросы по тегам