一个简单例子带你理解 依赖注入

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个简单例子带你理解 依赖注入相关的知识,希望对你有一定的参考价值。

  刚出来工作就遇到了一个棘手的问题:依赖注入

  公司的软件需求更新频率较高,所以前辈们为了满足需求,方便更新,就用到了依赖注入这个东西。

  在之前都没有听说过那个东西,所以一开始简直是蒙了,然后各种百度,发现依赖注入这个东西还是个热门话题!

 

  可是热门不代表自己能好理解,网上的好文章很多,可是自己慧根不够,看着看着就晕了。

  不过文章大豆提到了一个东西  反射  。完了,又是一个没听说过的名字(博主自学开发,可能软件专业的会提到)。

  于是接着各种百度  反射 ,大概了解了什么叫做 反射。可是这个时候又开始纠结反射的用法什么的(习惯性的联想思维,根本停不下来)。

  总之也是比较坎坷,后来发现,至少在我这个简单的例子里,仅仅用到了反射的一句代码。

  InterfaceDLL = Assembly.Load(namespacename).CreateInstance(namespacename + "." + classname);

 

  好吧,废话了好多,看到我这篇文章的朋友可能已经看了好多关于依赖注入的文章了,可是很多文章举的例子或者说明都不好理解(可能是我自己理解能力不足,或者没有遇到自己觉得通俗易懂的文章),下面就给大家做个简单的例子:

 

  首先,实现注入需要的材料:

  1.被注入的程序(主程序,相当于写好了的应用)

  2.一个接口

  3.实现了 2 接口的类

 

  这里的三个部分我们要分开编译。

  第一个项目我们写一个winform程序

  技术分享

  等下我们要拓展的或者说是变更的需求是点击“showname” 的功能。

  两个输入框的name分别是 Num1,Num2

 

  第二个项目我们写一个类库 命名为 InterfaceDLL,这个项目里只有一个接口 

 

  

namespace InterfaceDLL
{
    public interface MyInterface1
    {
        string ShowName(string name);
    }
}

  我们先编译项目二,得到一个dll 文件,接着我们在项目一引用得到的dll

  然后我们在项目一要做一下操作:

  1.Form1.cs 类里边引用我们的dll的命名空间:using InterfaceDLL;//

  2.然后在类里声明接口变量:MyInterface1 myinterface1;// 

  3.在Form1_Load事件里加上这句:myinterface1 = Assembly.Load(Num1.Text).CreateInstance(Num1.Text+ "." + Num2.Text) as MyInterface1 ;//

  4.在 showname 按钮的点击事件里写上:MessageBox.Show(myinterface1.ShowName("mm"));

  完成后,我们也编译项目一

 

  至此,项目一和项目二已经完成,接下来我们要做项目三

  项目三我们也是做一个类库项目tuozhan2dll ,项目三我们也要引用项目二的dll文件  

  然后我们在项目三创建的类Class1 实现 MyInterface1 接口:

namespace tuozhan2dll
{
    public class Class1:MyInterface1
    {
        string MyInterface1.ShowName(string name)
        {
            return "your name is "+name;
        }
    }
}

  然后我们编译项目三。

  三个项目的编译完成后,我们做一些测试前的操作:

  1.将项目三产生的dll 文件放到项目一的debug 目录下,让它跟程序处于同一目录。(注意:项目三的dll不可用进行重命名

 

 

  好了,我们直接在项目一的debug 目录下运行程序(注意,我们的项目一在项目三之前就已经编译好了

  我们在左边输入框输入项目三的命名空间tuozhan2dll,在右边的输入框输入项目三中实现了项目二接口的类 Class1

  然后点击 “showname” 按钮,结果如图:

  技术分享

 

  注意,主程序在编译后并不知道有项目三的dll存在,它是通过 反射(可以了解一下) 创建了项目三中Class1 的实例,而Class1 实现了接口 MyInterface1 。

  那我们要变更需求的时候,我么该怎么做呢?

  答案是,我们只需要修改项目三实现的方法就行,当然,你也可以创建一个新的项目实现项目二的接口

  比如我们把需求改成:

string MyInterface1.ShowName(string name)
        {
            return "I don‘t know who is "+name;
        }

  然后重新编译一下 项目三,把新生成的dll 替换原来项目一debug 下的文件

  结构如图:

  技术分享

 

这样就是一个完整的依赖注入例子了。

依赖注入的运用非常广泛,我现在也是刚接触一点皮毛,可能说的也不准,还望指出。

后话:之前百度的时候看到像软件的拓展插件呀就是运用注入实现的,然后自己去模拟实现了一下,以翻译应用为模型,功能拓展就是翻译功能,点击下拉框选择要翻译的目标语言,不过原理是一样的,这里其实是将拓展dll的命名空间还有类名动态的保存到配置文件,有兴趣的可以试试。这个过程看情况有时间再分享:

 

  技术分享

以上是关于一个简单例子带你理解 依赖注入的主要内容,如果未能解决你的问题,请参考以下文章

injection

深层理解Spring 控制反转和依赖注入,这一篇文够了

焊接@Produces依赖项具有空注入点

Spring依赖注入(DI)的理解

spring依赖注入,和控制反转。用自己的话说是怎么说的。最好能够用代码来解释

对Spring IOC的理解