Я изо всех сил пытаюсь понять части использования 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.