C# IoC学习笔记
<h2> 一、引言</h2><p> IoC-Invertion of Control,即控制反转,是一种程序设计思想。</p>
<p> 先初步了解几个概念:</p>
<p><strong> 依赖(Dependency)</strong>:就是有联系,表示一个类依赖于另一个类。</p>
<p><strong> 依赖倒置原则(DIP)</strong>:设计模式六大原则之一,是一种软件架构设计原则。</p>
<p><strong> 控制反转(IoC)</strong>:一种软件设计原则,上层对下层的依赖(即底层模块的获得)交给第三方。</p>
<p><strong> 依赖注入(DI)</strong>:实现IoC的一种方式、手段。</p>
<p><strong> IoC容器</strong>:依赖注入的框架,用来映射依赖,管理对象的创建和生存周期。</p>
<h2> 二、依赖</h2>
<p> 依赖就是有联系,有地方使用它就是有依赖它,下面看一个简单的示例:</p>
<p><img src="https://img2020.cnblogs.com/blog/1227623/202003/1227623-20200318114737994-1209610868.png" alt=""></p>
<div class="cnblogs_code"><img id="code_img_closed_45a746d5-4991-4ef6-a98c-c89d539a1122" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_45a746d5-4991-4ef6-a98c-c89d539a1122" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_45a746d5-4991-4ef6-a98c-c89d539a1122" class="cnblogs_code_hide">
<pre> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
{
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> BMW
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> Show()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">宝马</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ChinesePeople
{
</span><span style="color: rgba(0, 0, 255, 1)">private</span> BMW bmw = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> BMW();
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Run()
{
Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">今天开{bmw.Show()}上班</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
}
}
</span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
{
ChinesePeople people </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ChinesePeople();
BMW bmw </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> BMW();
people.Run();
Console.Read();
}
}</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p> 上面中国人开着宝马去上班,客户端有使用中国人、宝马汽车两个对象,中国人中有使用对象宝马汽车,我们可以从中找到三个依赖关系:</p>
<p> 客户端依赖对象ChinesePeople;</p>
<p> 客户端依赖对象BMW;</p>
<p> ChinesePeople依赖对象BMW;</p>
<h2> 三、依赖倒置原则</h2>
<p> 过些日子来了新需求,中国人不仅要开宝马去上班,还要开奔驰去上班,如果按照上面直接依赖关系的方式去做,我们就需要修改ChinesePeople类,让它实现一个参数为宝马的重载方法Run()。显然这样不是好的设计,我们总不能每次新增一种汽车(即修改下层模块)都要去修改ChinesePeople类吧(相对于汽车为上层模块),太麻烦了。。。</p>
<p> 先简单分析一下,耦合关系就是依赖关系,如果依赖关系很重,牵一发而动全身,将很难维护扩展,耦合关系越少,系统会越稳定,因此要较少依赖。</p>
<p> 定义:</p>
<p> A.高层模块不应依赖于底层模块,两者应该依赖于抽象。</p>
<p> B.抽象不应该依赖于细节,细节应该依赖于抽象。</p>
<p><img src="https://img2020.cnblogs.com/blog/1227623/202003/1227623-20200318115659629-1668063573.png" alt=""></p>
<p> 在这个图中,我们发现高层模块定义接口,将不直接依赖于下层模块,下层模块负责实现高层模块定义的接口,下面看一下示例:</p>
<div class="cnblogs_code"><img id="code_img_closed_140f9641-ecaf-4adf-8615-0844163b9f32" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_140f9641-ecaf-4adf-8615-0844163b9f32" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_140f9641-ecaf-4adf-8615-0844163b9f32" class="cnblogs_code_hide">
<pre> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
{
</span><span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> ICar
{
</span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> Show();
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> BMW : ICar
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> Show()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">宝马</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> BenZ : ICar
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> Show()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">奔驰</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> IPeople
{
</span><span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Run(ICar car);
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ChinesePeople : IPeople
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Run(ICar car)
{
Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">今天开{car.Show()}上班</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
}
}
</span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
{
ICar bmw </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> BMW();
ICar benz </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> BenZ();
IPeople people </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ChinesePeople();
people.Run(bmw);
people.Run(benz);
Console.Read();
}
}</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p> 运行结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/1227623/202003/1227623-20200318134106634-646398169.png" alt=""></p>
<p> 分析:上面代码中,ChinesePeople类不再依赖于具体的汽车,而是依赖于汽车的抽象,这样使得不管换什么样的汽车品牌,中国人都是可以开着去上班的,而且不需要修改ChinesePeople类。想一下,这样是不是挺好的,我们可以得出:上层不再依赖细节,相比面向实现,面向接口较好,因为抽象相比细节要更稳定。</p>
<h2> 四、控制反转</h2>
<p> 上面示例中,我们实现了具体的人和具体的汽车的隔离,具体人只和汽车的接口有关。但是Program中Main方法里的具体对象写死了,控制权变小,当我要修改美国人开着福特去上班时,就不得不要去修改代码,那怎么把控制权转移呢?</p>
<p> 下面看一个简单的示例(请先添加System.Configuration引用):</p>
<div class="cnblogs_code"><img id="code_img_closed_3446ea86-b64c-497d-992c-31875e69a361" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_3446ea86-b64c-497d-992c-31875e69a361" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_3446ea86-b64c-497d-992c-31875e69a361" class="cnblogs_code_hide">
<pre> <span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> ICar
{
</span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> Show();
}</span></pre>
</div>
<span class="cnblogs_code_collapse">ICar.cs</span></div>
<div class="cnblogs_code"><img id="code_img_closed_953820b4-ba83-4979-a910-e7d65711eb0a" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_953820b4-ba83-4979-a910-e7d65711eb0a" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_953820b4-ba83-4979-a910-e7d65711eb0a" class="cnblogs_code_hide">
<pre> <span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> IPeople
{
</span><span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Run(ICar car);
}</span></pre>
</div>
<span class="cnblogs_code_collapse">IPeople.cs</span></div>
<div class="cnblogs_code"><img id="code_img_closed_d62c3f43-e545-4f05-9383-c7e4e92f435b" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_d62c3f43-e545-4f05-9383-c7e4e92f435b" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_d62c3f43-e545-4f05-9383-c7e4e92f435b" class="cnblogs_code_hide">
<pre> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> BMW : ICar
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> Show()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">宝马</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
}
}</span></pre>
</div>
<span class="cnblogs_code_collapse">BMW.cs</span></div>
<div class="cnblogs_code"><img id="code_img_closed_2ea79a62-da5c-477a-9b56-689eb8c6a449" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_2ea79a62-da5c-477a-9b56-689eb8c6a449" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_2ea79a62-da5c-477a-9b56-689eb8c6a449" class="cnblogs_code_hide">
<pre> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ChinesePeople : IPeople
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Run(ICar car)
{
Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">今天开{car.Show()}上班</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
}
}</span></pre>
</div>
<span class="cnblogs_code_collapse">ChinesePeople.cs</span></div>
<div class="cnblogs_code"><img id="code_img_closed_da9a061f-e0df-4aac-93b9-46a9e51506dc" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_da9a061f-e0df-4aac-93b9-46a9e51506dc" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_da9a061f-e0df-4aac-93b9-46a9e51506dc" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)"><?</span><span style="color: rgba(255, 0, 255, 1)">xml version="1.0" encoding="utf-8" </span><span style="color: rgba(0, 0, 255, 1)">?></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">configuration</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">startup</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">supportedRuntime </span><span style="color: rgba(255, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">="v4.0"</span><span style="color: rgba(255, 0, 0, 1)"> sku</span><span style="color: rgba(0, 0, 255, 1)">=".NETFramework,Version=v4.6.1"</span> <span style="color: rgba(0, 0, 255, 1)">/></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">startup</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">appSettings</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">add </span><span style="color: rgba(255, 0, 0, 1)">key</span><span style="color: rgba(0, 0, 255, 1)">="People"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="LinkTo.Test.ConsoleIoC.ChinesePeople,LinkTo.Test.ConsoleIoC"</span><span style="color: rgba(0, 0, 255, 1)">/></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">add </span><span style="color: rgba(255, 0, 0, 1)">key</span><span style="color: rgba(0, 0, 255, 1)">="Car"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="LinkTo.Test.ConsoleIoC.BMW,LinkTo.Test.ConsoleIoC"</span><span style="color: rgba(0, 0, 255, 1)">/></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">appSettings</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">configuration</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<span class="cnblogs_code_collapse">App.config</span></div>
<div class="cnblogs_code"><img id="code_img_closed_7a76dd47-c0c7-4aa1-ae17-d95a5ef29229" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_7a76dd47-c0c7-4aa1-ae17-d95a5ef29229" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_7a76dd47-c0c7-4aa1-ae17-d95a5ef29229" class="cnblogs_code_hide">
<pre> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
{
</span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
{
</span><span style="color: rgba(0, 0, 255, 1)">#region</span> 反射+配置文件实现Ioc
<span style="color: rgba(0, 0, 255, 1)">string</span> people = ConfigurationManager.AppSettings[<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">People</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">];
</span><span style="color: rgba(0, 0, 255, 1)">string</span> car = ConfigurationManager.AppSettings[<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Car</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">];
Assembly assemblyPeople </span>= Assembly.Load(people.Split(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">,</span><span style="color: rgba(128, 0, 0, 1)">'</span>)[<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">]);
Assembly assemblyCar </span>= Assembly.Load(car.Split(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">,</span><span style="color: rgba(128, 0, 0, 1)">'</span>)[<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">]);
Type typePeople </span>= assemblyPeople.GetType(people.Split(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">,</span><span style="color: rgba(128, 0, 0, 1)">'</span>)[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">]);
Type typeCar </span>= assemblyPeople.GetType(car.Split(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">,</span><span style="color: rgba(128, 0, 0, 1)">'</span>)[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">]);
IPeople ipeople </span>=<span style="color: rgba(0, 0, 0, 1)"> (IPeople)Activator.CreateInstance(typePeople);
ICar icar </span>=<span style="color: rgba(0, 0, 0, 1)"> (ICar)Activator.CreateInstance(typeCar);
ipeople.Run(icar);
Console.Read();
</span><span style="color: rgba(0, 0, 255, 1)">#endregion</span><span style="color: rgba(0, 0, 0, 1)">
}
}</span></pre>
</div>
<span class="cnblogs_code_collapse">Program.cs</span></div>
<p> 上面代码中,我们使用反射+配置文件的方式,将对象创建的控制权转移到了配置文件,这就是所谓的<strong>控制反转</strong>。</p>
<p> 分析:控制反转是将对象创建的控制权交给了第三方,可以是IoC容器,它就相当于简单工厂。我们要什么对象,工厂就给我们什么对象,这样依赖关系就变了,它们(人和车)都依赖于IoC容器,通过IoC容器建立它们之间的依赖关系。(依赖对象不再直接通过new来获取)</p>
<p> 运行结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/1227623/202003/1227623-20200318142537527-1624088151.png" alt=""></p>
<h2> 五、依赖注入</h2>
<p> 上面说到的控制反转,我们了解到是将控制权转移,这是我们的目的。配置文件+反射是一种实现,而依赖注入则提供的是一种思想,或者说是实现IoC的手段。</p>
<p> 依赖注入是将对象的创建和绑定转移到被依赖对象的外部来实现,一般使用哪些方法来实现呢?</p>
<h4> 方法一:构造函数注入</h4>
<div class="cnblogs_code"><img id="code_img_closed_252b6731-4169-456d-a500-e9f6b00a18bb" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_252b6731-4169-456d-a500-e9f6b00a18bb" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_252b6731-4169-456d-a500-e9f6b00a18bb" class="cnblogs_code_hide">
<pre> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ChinesePeopleConstructor
{
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">readonly</span><span style="color: rgba(0, 0, 0, 1)"> ICar _car;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">依赖注入:构造函数注入</span>
<span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> ChinesePeopleConstructor(ICar car)
{
_car </span>=<span style="color: rgba(0, 0, 0, 1)"> car;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Run()
{
Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">今天开{_car.Show()}上班</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
}
}</span></pre>
</div>
<span class="cnblogs_code_collapse">ChinesePeopleConstructor.cs</span></div>
<div class="cnblogs_code"><img id="code_img_closed_b14c8769-2293-4852-a647-291023a814bc" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_b14c8769-2293-4852-a647-291023a814bc" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_b14c8769-2293-4852-a647-291023a814bc" class="cnblogs_code_hide">
<pre> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
{
</span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
{
</span><span style="color: rgba(0, 0, 255, 1)">#region</span> 依赖注入:构造函数注入<span style="color: rgba(0, 0, 0, 1)">
ICar bmw </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> BMW();
ChinesePeopleConstructor people </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ChinesePeopleConstructor(bmw);
people.Run();
Console.Read();
</span><span style="color: rgba(0, 0, 255, 1)">#endregion</span><span style="color: rgba(0, 0, 0, 1)">
}
}</span></pre>
</div>
<span class="cnblogs_code_collapse">Program.cs</span></div>
<h4> 方法二:属性注入</h4>
<div class="cnblogs_code"><img id="code_img_closed_3c3d0767-c249-4c90-8c15-d885896f7f67" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_3c3d0767-c249-4c90-8c15-d885896f7f67" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_3c3d0767-c249-4c90-8c15-d885896f7f67" class="cnblogs_code_hide">
<pre> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ChinesePeopleProperty
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">依赖注入:属性注入</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> ICar Car { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Run()
{
Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">今天开{Car.Show()}上班</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
}
}</span></pre>
</div>
<span class="cnblogs_code_collapse">ChinesePeopleProperty.cs</span></div>
<div class="cnblogs_code"><img id="code_img_closed_553358fd-6675-4efb-9adc-4775643891ba" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_553358fd-6675-4efb-9adc-4775643891ba" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_553358fd-6675-4efb-9adc-4775643891ba" class="cnblogs_code_hide">
<pre> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
{
</span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
{
</span><span style="color: rgba(0, 0, 255, 1)">#region</span> 依赖注入:属性注入<span style="color: rgba(0, 0, 0, 1)">
ICar bmw </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> BMW();
ChinesePeopleProperty people </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ChinesePeopleProperty
{
Car </span>=<span style="color: rgba(0, 0, 0, 1)"> bmw
};
people.Run();
Console.Read();
</span><span style="color: rgba(0, 0, 255, 1)">#endregion</span><span style="color: rgba(0, 0, 0, 1)">
}
}</span></pre>
</div>
<span class="cnblogs_code_collapse">Program.cs</span></div>
<h4> 方法三:接口注入</h4>
<div class="cnblogs_code"><img id="code_img_closed_ceac958a-63f8-4204-be07-6fa37eee992a" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_ceac958a-63f8-4204-be07-6fa37eee992a" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_ceac958a-63f8-4204-be07-6fa37eee992a" class="cnblogs_code_hide">
<pre> <span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> IDependent
{
</span><span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> SetDependent(ICar icar);
}</span></pre>
</div>
<span class="cnblogs_code_collapse">IDependent.cs</span></div>
<div class="cnblogs_code"><img id="code_img_closed_cb5346be-7134-47e1-94a7-d6d444ab5288" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_cb5346be-7134-47e1-94a7-d6d444ab5288" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_cb5346be-7134-47e1-94a7-d6d444ab5288" class="cnblogs_code_hide">
<pre> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ChinesePeopleInterface : IDependent
{
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> ICar _car;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">依赖注入:接口注入</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> SetDependent(ICar car)
{
_car </span>=<span style="color: rgba(0, 0, 0, 1)"> car;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Run()
{
Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">今天开{_car.Show()}上班</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
}
}</span></pre>
</div>
<span class="cnblogs_code_collapse">ChinesePeopleInterface.cs</span></div>
<div class="cnblogs_code"><img id="code_img_closed_3d4e98a6-cc81-43ea-8ab8-e7e863ce51a9" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_3d4e98a6-cc81-43ea-8ab8-e7e863ce51a9" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_3d4e98a6-cc81-43ea-8ab8-e7e863ce51a9" class="cnblogs_code_hide">
<pre> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
{
</span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
{
</span><span style="color: rgba(0, 0, 255, 1)">#region</span> 依赖注入:接口注入<span style="color: rgba(0, 0, 0, 1)">
ICar bmw </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> BMW();
ChinesePeopleInterface people </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ChinesePeopleInterface();
people.SetDependent(bmw);
people.Run();
Console.Read();
</span><span style="color: rgba(0, 0, 255, 1)">#endregion</span><span style="color: rgba(0, 0, 0, 1)">
}
}</span></pre>
</div>
<span class="cnblogs_code_collapse">Program.cs</span></div>
<h2> 六、IoC容器</h2>
<p> IoC容器是一个DI框架,主要功能有一下几点:</p>
<p> A.动态创建、注入依赖对象;</p>
<p> B.管理对象生命周期;</p>
<p> C.映射依赖关系;</p>
<p> 常见的IoC容器:Spring.NET,Castle Windsor, Ninject,Autofac,Unity。。。</p>
<h4> 6.1、Unity容器使用</h4>
<p> 在上一篇《C# AOP学习笔记》的【使用EntLib\PIAB Unity实现AOP(带配置)】中,已经使用Unity容器实现了IoC,让我们再来看看配置文件:</p>
<p><img src="https://img2020.cnblogs.com/blog/1227623/202003/1227623-20200320085401133-843508696.png" alt=""></p>
<p> 假如只需要IoC不需要AOP,container是这样子的:</p>
<div class="cnblogs_code"><img id="code_img_closed_45bb612c-cd0a-403f-ba4e-4ef55916aa73" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_45bb612c-cd0a-403f-ba4e-4ef55916aa73" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_45bb612c-cd0a-403f-ba4e-4ef55916aa73" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">configuration</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">configSections</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">section </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="unity"</span><span style="color: rgba(255, 0, 0, 1)"> type</span><span style="color: rgba(0, 0, 255, 1)">="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"</span><span style="color: rgba(0, 0, 255, 1)">/></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">configSections</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">unity</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">sectionExtension </span><span style="color: rgba(255, 0, 0, 1)">type</span><span style="color: rgba(0, 0, 255, 1)">="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"</span><span style="color: rgba(0, 0, 255, 1)">/></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">containers</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">container </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="IoCContainer"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">注册匹配规则:前面是完整类型名称,后面是所在的dll名称。</span><span style="color: rgba(0, 128, 0, 1)">--></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">register </span><span style="color: rgba(255, 0, 0, 1)">type</span><span style="color: rgba(0, 0, 255, 1)">="LinkTo.Test.ConsoleAop.UnityConfigAOP.IUserProcessor,LinkTo.Test.ConsoleAop"</span><span style="color: rgba(255, 0, 0, 1)"> mapTo</span><span style="color: rgba(0, 0, 255, 1)">="LinkTo.Test.ConsoleAop.UnityConfigAOP.UserProcessor,LinkTo.Test.ConsoleAop"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">register</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">container</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">containers</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">unity</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">configuration</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p> 从IoC的注册匹配规则可以看出,前面是完整类型名称,后面是所在的dll。这个就比较厉害了,假如一个系统有扩展的功能或者个性要求,只需配置使用新的dll即可,原有系统不需要改代码。这样,除了很好地符合了"开闭原则"外,对于构建一个可配置可扩展的系统,是一个非常厉害的利器。 </p>
<p> </p>
<p> 参考自:</p>
<p> https://www.cnblogs.com/jdzhang/p/7104351.html</p>
<p> 推荐博文:</p>
<p> 基于接口设计三层架构</p><br><br>
来源:https://www.cnblogs.com/atomy/p/12516304.html
頁:
[1]