我试图让IoC与C#中的Unity一起工作,以为将包装器/复合类传递给子代。
组成多个类的顶级类提供了组成类需要访问的一些常用功能。
说明:
// The top composite class
public class Context : IContext {
public ISomething SomethingProcessor { get; }
public IAnother AnotherProcessor { get; }
public Context(ISomething something, IAnother another) {
this.SomethingProcessor = something;
this.AnotherProcessor = processor;
}
// A function that individual classes need access to, which itself calls one of the children.
public string GetCommonData() {
return this.AnotherProcessor.GetMyData();
}
}
public class Something : ISomething {
private _wrapper;
public Something(IContext context) {
this._wrapper = context;
}
// This class has no knowledge of IAnother, and requests data from the master/top class, which knows where to look for whatever.
public void Do() {
Console.WriteLine(_wrapper.GetCommonData());
}
}
public class Another : IAnother {
public string GetMyData() {
return "Foo";
}
}
如果您不使用IoC,这很容易,因为Context类的构造函数变为:
public Context() {
this.SomethingProcessor = new Processor(this);
this.AnotherProcessor = new Another();
}
但是,当您使用IoC时,“ this”的概念尚不存在,因为它尚未由注入器构造。取而代之的是循环依赖。
container.RegisterType<ISomething, Something>();
container.RegisterType<IAnother, Another>();
container.RegisterType<IContext, Context>();
var cxt = container.Resolve<IContext>(); // StackOverflowException
上面的示例已大大简化,以说明该概念。我正在努力寻找处理此类结构以启用IOC的“最佳实践”方法。
答案 0 :(得分:2)
工厂模式是一种基于其他依赖关系或逻辑选择构造对象的方式。
工厂方法:“定义用于创建对象的接口,但让 实现该接口的类决定要哪个类 实例化。 Factory方法允许类将实例化延迟到 子类”(c)GoF。
很多建筑,因此得名Factory Pattern
可以与DI一起使用的原始代码示例
public class ContextFactory : IContextFactory {
_anotherProcessor = anotherProcessor;
public ContextFactory(IAnotherProcessor anotherProcessor) {
//you can leverage DI here to get dependancies
}
public IContext Create(){
Context factoryCreatedContext = new Context();
factoryCreatedContext.SomethingProcessor = new SomethingProcessor(factoryCreatedContext )
factoryCreatedContext.AnotherProcessor = _anotherProcessor;
//You can even decide here to use other implementation based on some dependencies. Useful for things like feature flags.. etc.
return context;
}
}
也许您可以解决这个问题? -但是这里仍然存在循环引用问题,我永远也不会提交这种代码。
这里的问题需要重点关注GetCommonData
您的SomethingProcessor
不应依赖另一个类中的方法。在这里可以使用In Inheritance,但是Inheritance会变得非常复杂。
最好的方法是确定两个或多个其他地方都需要的一件事,并将其分解为新的依赖关系。这就是您反转控制的方式。
提示:
不要过度使用接口-在认为您将要使用多态的接口上使用接口,例如必须保证您已实现特定方法/属性的不同对象的集合。否则,您将无法使用接口并增加复杂性。 DI不必使用接口,它可以是一个具体的实现。存储库上的接口很好用,因为您可以轻松地切换数据库,但是实际上不需要像这样的工厂接口。
答案 1 :(得分:1)
我不知道此模式的名称,即使它是不好的做法,也可以,但是您可以通过创建一个绑定“ IContext”的方法来解决“双重绑定”的问题,而不是在构造函数中完成。
例如
1)ISomething
有一种void BindContext(IContext context)
方法
2)您可以这样实现:
class Something : ISomething
{
IContext _wrapper;
// ... nothing in constructor
public void BindContext(IContext context)
{
_wrapper = context;
}
}
3)在Something构造函数中删除IContext
依赖项注入。
然后从上下文构造函数中调用它:
public Context(ISomething something, IAnother another) {
this.SomethingProcessor = something;
this.SomethingProcessor.BindContext(this);
// same for IAnother
}
您对IAnother
执行相同的操作。您甚至可以提取一些通用接口“ IBindContext”,使事情变得更“干”(不要重复自己),并使IAnother
和ISomething
继承自它。
未经测试,再说一遍:不确定这是进行此类依赖项设计的最佳方法。如果有另一个答案可以对此提供最新的见解,我会感到很高兴。