Я пытаюсь понять части использования StructureMap. В частности, в документации заявление делается в отношении общего антишаблона использования StructureMap в качестве локатора службы только вместо инъекции конструктора (образцы коды прямо из StructureMap документации):Инъекция конструктора и когда использовать локатор обслуживания
public ShippingScreenPresenter()
{
_service = ObjectFactory.GetInstance<IShippingService>();
_repository = ObjectFactory.GetInstance<IRepository>();
}
вместо:
public ShippingScreenPresenter(IShippingService service, IRepository repository)
{
_service = service;
_repository = repository;
}
Это прекрасно в течение очень короткого графа объектов, но при работе с объектами много уровней глубокими, означает ли это, что вы должны пройти вниз всю зависимость, необходимую для более глубоких объектов прямо с вершины? Разумеется, это нарушает инкапсуляцию и предоставляет слишком много информации о реализации более глубоких объектов.
Предположим, что я использую шаблон Active Record, поэтому моей записи нужен доступ к хранилищу данных, чтобы иметь возможность сохранять и загружать себя. Если эта запись загружается внутри объекта, вызывает ли объект ObjectFactory.CreateInstance() и передает его в конструктор активной записи? Что делать, если этот объект находится внутри другого объекта. Требуется ли IRepository в качестве собственного параметра дальше? Это предоставит родительскому объекту тот факт, что в данный момент мы получаем доступ к хранилищу данных, что, вероятно, не должен знать внешний объект.
public class OuterClass
{
public OuterClass(IRepository repository)
{
// Why should I know that ThingThatNeedsRecord needs a repository?
// that smells like exposed implementation to me, especially since
// ThingThatNeedsRecord doesn't use the repo itself, but passes it
// to the record.
// Also where do I create repository? Have to instantiate it somewhere
// up the chain of objects
ThingThatNeedsRecord thing = new ThingThatNeedsRecord(repository);
thing.GetAnswer("question");
}
}
public class ThingThatNeedsRecord
{
public ThingThatNeedsRecord(IRepository repository)
{
this.repository = repository;
}
public string GetAnswer(string someParam)
{
// create activeRecord(s) and process, returning some result
// part of which contains:
ActiveRecord record = new ActiveRecord(repository, key);
}
private IRepository repository;
}
public class ActiveRecord
{
public ActiveRecord(IRepository repository)
{
this.repository = repository;
}
public ActiveRecord(IRepository repository, int primaryKey);
{
this.repositry = repository;
Load(primaryKey);
}
public void Save();
private void Load(int primaryKey)
{
this.primaryKey = primaryKey;
// access the database via the repository and set someData
}
private IRepository repository;
private int primaryKey;
private string someData;
}
Любые мысли будут оценены.
Саймон
РЕДАКТИРОВАТЬ: мнение, кажется, что инъекция должна начинаться в верхнем слое. ActiveRecord будет введен в ThingThatNeedsRecord, который вводится в OuterClass. Проблема с этим заключается в том, что если ActiveRecord необходимо создать с помощью параметра времени выполнения (например, идентификатор записи для извлечения). Если я вставляю ActiveRecord в ThingThatNeedsRecord прямо вверху, мне как-то нужно выяснить, какой идентификатор должен быть в этот момент (который предоставляет верхний уровень реализации, которого он не должен), или мне нужно иметь частично сконструированный ActiveRecord и установите Идентификатор позже. Это становится более сложным, если мне нужно N записей и не будет знать до выполнения логики внутри ThingThatNeedsRecord.
Возможный дубликат: http://stackoverflow.com/questions/4570750/dependency-injection-turtles-all-the-way-down –
Связанный: http://stackoverflow.com/questions/2420193/dependency-injection- Конструктор-безумие/2420245 # 2420245 –