我是依赖注入的新手,仍然试图绕过它。据我了解,根据书籍Dependency Injection in .NET的最佳实践表明,对象图是在应用程序启动时在Composition Root创建的,并且在应用程序中不再访问容器。
当用户点击新/打开按钮时会发生什么?
通常我会创建所需对象图部分的新实例(Forest
)但是如果我不应该访问容器,我是否应该调用传播对象图的clear方法?我是否以某种方式使用了生命周期管理,并确保目前没有对象图部分的新引用?
编辑:
使用MVVM / WPF的示例
public class Bootstrapper {
public void Initialize() {
Container.Register<IMainViewModel, MainViewModel>();
Container.Register<IForest, Forest>();
Container.Register<ITrees, Trees>();
Container.Register<ITree, Tree>();
}
}
public class MainViewModel : IMainViewModel {
private IForest _forest;
public MainViewModel(IForest forest) { _forest = forest; }
public void New() { Forest.Clear(); }
public void AddTrees(){ _trees.Add(new Tree()); }
}
public class ViewModel : IViewModel {
private ITrees _trees;
private ITree _selectedTree;
public ViewModel(ITrees trees){ _trees = trees; }
public void AddTrees() { _trees.Add(new Tree()); }
}
public class Forest : IForest {
private ITrees _trees;
public Forest(ITrees trees){ _trees = trees; }
public void AddTree(ITree tree){ _trees.Add(tree); }
public void Clear(){ _trees.Clear(); }
}
public class Trees : ITrees {
public List<ITree> trees = new List<ITree>();
public void Add(ITree tree){ trees.Add(tree); }
public void Clear(){ trees.Clear(); }
}
答案 0 :(得分:1)
根据.NET中的Dependency Injection一书,指出对象图是在组合根中的app启动时创建的,并且在应用程序中再次访问容器。
本书没有说明应用程序的对象图只应创建一次,并且它当然不会声明应该从应用程序访问容器。
然而,本书的第1版陈述了以下内容(不是确切的引用):
总结:
但如果我不应该访问容器,我是否应该调用传播对象图的清晰方法?
这个看似矛盾的答案是:抽象!
为了能够从已构建的组件中懒惰地构造对象图,您可以定义特定的抽象(更精确的抽象工厂),以允许创建该特定服务。此工厂抽象可以在应用程序级别定义,并在组合根目录中实现。
例如:
// Defined in application
public interface IForestFactory
{
IForest Create();
}
// Defined inside the Composition Root
public class ForestFactory : IForestFactory
{
private readonly Container container;
public ForestFactory(Container container) {
this.container = container;
}
public IForest Create() {
return this.container.GetInstance<IForest>();
}
}
// Inside the Bootstrapper
var factory = new ForestFactory(Container);
Container.Register<IForestFactory>(() => factory);
然而,second edition of the book描述了这些工厂通常是代码气味。通常最好使用Virtual Proxy。,而不是使用工厂
虚拟代理是一个应该懒惰创建的对象的替身。然而,虚拟代理实现与延迟创建的对象相同的抽象。这允许将虚拟代理注入到消费者中,而消费者不必知道虚拟代理的存在。
在您的情况下,这意味着您为IForest
创建了一个虚拟代理,例如:
// Defined inside the Composition Root
public class LazyForestProxy : IForest
{
private readonly Container container;
public LazyForestProxy(Container container){
this.container = container;
}
// Implement IForest members
void IForest.Run() {
var forest = GetInstance();
// Forward the call to the 'real' forest
forest.Run();
}
private IForest GetInstance() {
return this.container.GetInstance<IForest>();
}
}