回答我的问题,这是关于循环依赖的一半:
c# ASP。. NET依赖注入与IoC容器的复杂性
演示者依赖于IView。而Page(实现IView)依赖于演示者。其他人已经解决了这个问题,从构造函数注入到属性注入
我不喜欢这样,因为我觉得你现在需要让公共属性可以在外部修改,并且也成为开发人员的责任来初始化。
但是我似乎可以用另一种方法解决这个问题。
通过拥有默认构造函数和重载参数化构造函数的页面,您可以通过反射调用无参数构造函数来创建对象然后通过注入依赖来调用重载的那个。
我将举例说明:
class TestObject
{
public string Name { get; set; }
public TestObject()
{
Name = "Constructed with no args";
Console.WriteLine("constructor hash code: " + GetHashCode());
}
public TestObject(string name)
{
this.Name = name;
Console.WriteLine("constructor hash code: " + GetHashCode());
}
}
这个对象可以简单地构造:
var obj = Activator.CreateInstance<TestObject>();
或
var obj = new TestObject();
但是我可以通过反射使用重载的构造函数注入依赖:
ConstructorInfo ctor = obj.GetType().GetConstructors()[1];
ctor.Invoke(obj, new[] { "injected" });
我能够使用这种方法来连接structuremap,以便在创建后注册实例,然后注入依赖项。
当然,我们可以使用常规方法注入依赖项,但这又稍微破坏了封装,所以你可以调用这个再次重写依赖项。
作为构造函数,它不能简单地通过静态代码到达。
但是我不知道我是怎么想的,这感觉有点像一个hack或者我可以在c#中不小心做的事情。
我想听听你的想法
谢谢。
我不喜欢这种反射的使用,因为它意味着你不能很容易地创建一个没有IoC容器的视图/演示器
解决IoC容器需求的一种方法是使用工厂来轻松创建视图/呈现器,并将反射逻辑放置在工厂中。
然而,在这一点上,你可以有一个简单的属性或Initialize(view)
/Initialize(presenter)
方法。调用这些方法的责任被工厂或IoC容器(充当工厂)从开发人员那里拿走了。
在构造时将依赖项传递给对象的另一种方法是传递一个可以将依赖项构建到对象的工厂。最简单的工厂形式是简单的Func
。
void Main()
{
var controller = Controller.Create (c => new View (c));
}
class Controller {
private View view;
// This could also be a constructor, but I prefer to think of this
// as a factory method.
public static Controller Create (Func<Controller, View> viewBuilder) {
var controller = new Controller ();
var view = viewBuilder (controller);
controller.Initialize (view);
return controller;
}
protected Controller() {
}
protected void Initialize (View view) {
this.view = view;
}
}
class View {
private Controller controller;
public View (Controller controller) {
this.controller = controller;
}
}
如果你坚持有一对构造函数,我会使无参数构造函数保护,除非它真的是有效的创建视图/呈现者没有呈现者/视图。这将防止有人错误地使用该构造函数,因为没有反射就无法在构造后初始化视图/呈现器。
虽然我认为这是一个稍微好一点的反射的想法,将使一个无参数的构造函数是受保护的,和一个受保护的初始化方法。
public class TestObject
{
protected TestObject () {
}
public TestObject (string name) {
Initialize (name)
}
protected Initialize (string name) {}
}
这强制你不能在没有名字的情况下构造它,除非你使用反射。反射将被封装在一个工厂中,这将确保Initialize
也被调用。