我正在努力理解 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 中,而 ThingThatNeedsRecord 又被注入到 OuterClass 中。这样做的问题是,如果 ActiveRecord 需要使用运行时参数(例如要检索的记录的 id)进行实例化。如果我在顶部将 ActiveRecord 注入到 ThingThatNeedsRecord 中,我必须以某种方式弄清楚此时需要什么 id(它将顶层暴露给它不应该实现的实现),或者我必须有一个部分构造的 ActiveRecord并稍后设置 Id。如果我需要 N 条记录并且直到在 ThingThatNeedsRecord 中执行逻辑才会知道,这会变得更加复杂。