代码之家  ›  专栏  ›  技术社区  ›  David Anderson

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

  •  1
  • David Anderson  · 技术社区  · 15 年前

        private RootWorkItem m_RootWorkItem;
        [RootWorkItem(Inject = true)]
        public RootWorkItem RootWorkItem {
    
            get {
                if (m_RootWorkItem == null) {
                    m_RootWorkItem = new RootWorkItem();
                }
                return m_RootWorkItem;
            }
        }
    

    请注意,RootWorkItem是我设计的一个类,它包含一个服务集合(collection)。基本上,我的所有服务都是使用reflection和Activator.CreateInstance从外部DLL文件加载的,并放入RootWorkItem.services中。

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

    这些DI模式实际上是如何“注入”到“属性”中的?我知道DI的概念,但我正试图为一个对象编写我自己的、非常基本的DI。我一直在与反射吨捣乱,试图找到一些合适的方法来做到这一点,我甚至不接近提出一个正确的方法来做到这一点。

    编辑以获得更清晰的问题:

    即:

        class MyForm : Form {
            [RootWorkItem(Inject = true)]
            public RootWorkItem RootWorkItem { get; set; }
        end class
    
        class Program {
            Main {
                MyForm form = new MyForm();
                form.Show();
            }
        end class
    

    如果没有任何东西通知服务它是被创建的或需要被注入的,那么它如何知道在创建窗体时注入属性值?

    2 回复  |  直到 15 年前
        1
  •  5
  •   Nader Shirazie    15 年前

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

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

    要知道,因为您使用DI框架来创建注入依赖项的对象。在本例中,您使用DI框架来创建表单,这样它就知道对象并可以注入依赖项。

    而不是

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

    MyForm form = DIFramework.CreateForm(typeof(MyForm));
    form.Show();
    

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

        2
  •  1
  •   Enigmativity    15 年前

    现在,你的例子在我看来是错的。属性位于只读属性上,该属性不能通过反射或任何其他方式设置。我希望你的例子是这样的:

    [RootWorkItem(Inject = true)]
    private RootWorkItem m_RootWorkItem;
    public RootWorkItem RootWorkItem {
    
        get {
            if (m_RootWorkItem == null) {
                m_RootWorkItem = new RootWorkItem();
            }
            return m_RootWorkItem;
        }
    }
    

    而且,因为你注入了 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; }
    

    最后,我不确定为什么属性类型与属性类型和名称相同。我会期待更像这样的事情:

    [Inject(true)]
    public RootWorkItem RootWorkItem { get; private set; }
    

    我不知道你用的是什么框架,所以我不能评论 true

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

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

    MyForm 实例。相反,您应该以某种方式向DI容器注册 我的窗体 键入,然后使用容器为您创建实例。然后它将创建实例,但在将实例返回给您之前,它将注入依赖项(它通过对属性的反射来发现依赖项)。

    // configure at start-up
    container.Register<MyForm>();
    
    // some point later in your code
    MyForm mf = container.Resolve<MyForm>();
    
    推荐文章