Введя правильный тип в мой бизнес-класс с помощью 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, и тогда каждый репозиторий может сообщить вам, несут ли они ответственность за обработку этого запроса.
- Вы можете включить это в голову и сказать, что у меня есть список репозиториев, мне нужен сервис, который берет эти репозитории и возвращает одно конкретное в зависимости от набора бизнес-правил (по сути, фабрика). Хотя этот подход делает решение немного дружественным к юнит-тестам.
Просто некоторые варианты для вас, чтобы рассмотреть:)