C# DI实际上是如何对属性进行注入的?

C# DI实际上是如何对属性进行注入的?,c#,dependency-injection,C#,Dependency Injection,我绞尽脑汁找不到合适的答案,所以我们开始吧!我的每种形式或对象都具有以下属性: private RootWorkItem m_RootWorkItem; [RootWorkItem(Inject = true)] public RootWorkItem RootWorkItem { get { if (m_RootWorkItem == null) { m_RootWorkItem = new Ro

我绞尽脑汁找不到合适的答案,所以我们开始吧!我的每种形式或对象都具有以下属性:

    private RootWorkItem m_RootWorkItem;
    [RootWorkItem(Inject = true)]
    public RootWorkItem RootWorkItem {

        get {
            if (m_RootWorkItem == null) {
                m_RootWorkItem = new RootWorkItem();
            }
            return m_RootWorkItem;
        }
    }
注意,RootWorkItem是我设计的一个类,它包含一个服务集合(collection)。基本上,我的所有服务都是使用反射和Activator.CreateInstance从外部DLL文件加载的,并放入RootWorkItem.services中

但我究竟如何才能将创建的第一个RootWorkItem“注入”到程序中标记有我的属性的其他RootWorkItem中呢

这些DI模式实际上是如何“注入”到“属性”中的?我知道DI的概念,但我正试图为一个对象编写我自己的、非常基本的DI。我一直在尝试寻找一些合适的方法来做这件事,我甚至还没有找到一个正确的方法来做这件事

编辑以获得更清晰的问题: DI框架/服务如何知道何时创建了包含要注入的属性的对象

即:


如果没有任何东西通知服务它已创建或需要注入属性值,那么它如何知道在创建表单时注入属性值?

通常,依赖注入框架使用属性和反射来发现哪些字段、属性,类的方法要求在创建时注入依赖项,然后使用反射来实际注入依赖项,从而绕过正常的访问器限制,例如,注入到私有字段中

我觉得你的例子不对。属性位于只读属性上,该属性不能通过反射或任何其他方式设置。我希望您的示例如下所示:

[RootWorkItem(Inject = true)]
private RootWorkItem m_RootWorkItem;
public RootWorkItem RootWorkItem {

    get {
        if (m_RootWorkItem == null) {
            m_RootWorkItem = new RootWorkItem();
        }
        return m_RootWorkItem;
    }
}
[Inject(true)]
public RootWorkItem RootWorkItem { get; private set; }
您的混淆是否可能源于属性的放置

此外,由于您正在将
m_RootWorkItem
的值注入到字段中,因此不再需要保护您的属性

[RootWorkItem(Inject = true)]
private RootWorkItem m_RootWorkItem;
public RootWorkItem RootWorkItem {

    get {
        return m_RootWorkItem;
    }
}
因此,您可以进一步使用自动实现的属性:

[RootWorkItem(Inject = true)]
public RootWorkItem RootWorkItem { get; private set; }
最后,我不确定为什么属性类型与属性类型和名称相同。然后我会期待更像这样的事情:

[RootWorkItem(Inject = true)]
private RootWorkItem m_RootWorkItem;
public RootWorkItem RootWorkItem {

    get {
        if (m_RootWorkItem == null) {
            m_RootWorkItem = new RootWorkItem();
        }
        return m_RootWorkItem;
    }
}
[Inject(true)]
public RootWorkItem RootWorkItem { get; private set; }
我不知道您使用的是什么框架,因此无法对
true
参数的作用进行评论,因此我将其逐字包含在内

由于正在编辑的问题而被编辑

您缺少了依赖项注入框架也是一个抽象工厂的概念

因此,您不会直接创建
MyForm
实例。相反,您可以通过某种方式向DI容器注册
MyForm
类型,然后使用该容器为您创建实例。然后,它将创建实例,但在将实例返回给您之前,它将注入依赖项(通过对属性的反射发现)

例如:

// configure at start-up
container.Register<MyForm>();

// some point later in your code
MyForm mf = container.Resolve<MyForm>();
//启动时配置
container.Register();
//代码后面的某个点
MyForm mf=container.Resolve();

通常,依赖项注入框架使用属性和反射来发现类的哪些字段、属性和方法需要在创建时注入依赖项,然后使用反射来实际注入依赖项-从而绕过正常的访问器限制-注入到私有字段,比如说

我觉得你的例子不对。属性位于只读属性上,该属性不能通过反射或任何其他方式设置。我希望您的示例如下所示:

[RootWorkItem(Inject = true)]
private RootWorkItem m_RootWorkItem;
public RootWorkItem RootWorkItem {

    get {
        if (m_RootWorkItem == null) {
            m_RootWorkItem = new RootWorkItem();
        }
        return m_RootWorkItem;
    }
}
[Inject(true)]
public RootWorkItem RootWorkItem { get; private set; }
您的混淆是否可能源于属性的放置

此外,由于您正在将
m_RootWorkItem
的值注入到字段中,因此不再需要保护您的属性

[RootWorkItem(Inject = true)]
private RootWorkItem m_RootWorkItem;
public RootWorkItem RootWorkItem {

    get {
        return m_RootWorkItem;
    }
}
因此,您可以进一步使用自动实现的属性:

[RootWorkItem(Inject = true)]
public RootWorkItem RootWorkItem { get; private set; }
最后,我不确定为什么属性类型与属性类型和名称相同。然后我会期待更像这样的事情:

[RootWorkItem(Inject = true)]
private RootWorkItem m_RootWorkItem;
public RootWorkItem RootWorkItem {

    get {
        if (m_RootWorkItem == null) {
            m_RootWorkItem = new RootWorkItem();
        }
        return m_RootWorkItem;
    }
}
[Inject(true)]
public RootWorkItem RootWorkItem { get; private set; }
我不知道您使用的是什么框架,因此无法对
true
参数的作用进行评论,因此我将其逐字包含在内

由于正在编辑的问题而被编辑

您缺少了依赖项注入框架也是一个抽象工厂的概念

因此,您不会直接创建
MyForm
实例。相反,您可以通过某种方式向DI容器注册
MyForm
类型,然后使用该容器为您创建实例。然后,它将创建实例,但在将实例返回给您之前,它将注入依赖项(通过对属性的反射发现)

例如:

// configure at start-up
container.Register<MyForm>();

// some point later in your code
MyForm mf = container.Resolve<MyForm>();
//启动时配置
container.Register();
//代码后面的某个点
MyForm mf=container.Resolve();

您提出了正确的问题:“如果没有任何内容通知服务它已创建或需要注入,那么它如何知道在创建表单时注入属性值?”

如果您说“如果没有任何东西通知服务它是创建的或需要注入的”,那么DI框架就不能完成它的工作,这也是正确的

但是,DI框架确实知道,因为您使用DI框架来创建注入依赖项的对象。在本例中,您使用DI框架来创建表单,因此它可以感知对象并可以注入依赖项

而不是

MyForm form = new MyForm(); 
form.Show();

现在,您的DI框架了解了对象


本质上,
new
是DI的敌人,因为它意味着调用者正在控制对象的构造。取而代之的是,调用者将责任留给其他人,即DI框架。调用者应该只要求DI框架提供/构造/配置对象。

你问的问题是正确的:“它是如何知道