Я смиряюсь с проблемой, связанной с AutoFac и абстрактным шаблоном завода. Мой пример - это сервис для использования IRepositoryFactory для создания репозитория на основе JSON или InMemory, связанных с вводом пользователя.Использование Autofac для переключения бетонной реализации абстрактной фабрики
// Abstract Factory
public interface IRepositoryFactory{
IRepository Create(string databaseIdentifier);
}
// JSON
public class JsonRepositoryFactory{
public IRepository Create(string databaseIdentifier){
return new JsonRepository(databaseIdentifier);
}
}
// InMemory
public class MemoryRepository{
public IRepository Create(string databaseIdentifier){
return new MemoryRepository(databaseIdentifier);
}
}
Служба должна вытащить завод путем инжекции конструктора.
public interface IShopService{
public string Name {get;}
}
public class BeerShop : IShopService {
public string Name {get; private set;}
private readonly IRepository _repository;
public BeerShop(IRepositoryFactory repositoryFactory){
Name = "beershop";
_repository = repositoryFactory.Create(Name);
}
}
До сих пор я доволен этим. Но инициализация не моя любимая.
var builder = new ContainerBuilder();
var userInput = ReadInput();
if(userInput = "json")
builder.RegisterType<IRepositoryFactory>().As<JsonRepositoryFactory>();
else
builder.RegisterType<IRepositoryFactory>().As<MemoryRepositoryFactory>();
builder.RegisterType<IShopService>.As<BeerShop>();
var container = builder.build();
[...]
var service = container.Resolve<IShoptService>();
// and so on ...
Это правильный подход к его решению? Я не убежден в моем собственном дизайне, потому что он заставляет пользователя вводить до инициализации контейнера. Что делать, если пользователь должен изменить репозиторий во время выполнения? Является ли абстрактный шаблон завода правильным инструментом для решения этой проблемы?
Ваш 'BeerShop' делает слишком много: [инжекторы должны быть простыми] (http://blog.ploeh.dk/2011/03/03/InjectionConstructorsshouldbesimple/). Если вы переместите вызов 'factory.Create' из конструктора в Корзину композиции, вы больше не требуете этой заводской абстракции. Также обратите внимание, что [заводские абстракции - запах кода] (https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=100). – Steven
Я согласен с Стивеном. Ваш клиент (который является BeerShop), похоже, не будет использовать тот же код/логику для другой вещи, например: colashoop. Также не используйте завод, если у вас нет других шансов. Потому что фабрика приносит сложность. Похоже, вам нужно это разделение на более низком уровне. Репозиторий будет таким же, но он будет использовать json или memory как Db. Изменение db во время выполнения очень опасно. Вы напишете что-нибудь в json и прочитаете из памяти по пользовательскому входу при той же самой runtime ??? –