记录对依赖注入的小小理解和autofac的简单封装
首先,我不是一个开发者,只是业余学习者。其次我的文化水平很低,写这个主要是记录一下当前对于这块的理解,因为对于一个低水平 的业余学习者来说,忘记是很平常的事,因为接触、应用的少,现在理解,可能过段时间就会忘了,自己记录下来应该可以少走些弯路,以免从头再来查找资料。
另外,如果我的记录能帮忙到一些朋友的话,也难免会有些小满足的。学习的门槛除了理解能力,绝大部分来自于英文水平和专业术语,我希望的是我能用比较通俗易懂的表达,获得大家的理解,更希望大牛们是如是做的,所以写这个更希望的是能得到大牛的帮助。
下面是我对依赖注入在应用场景的理解
从框架设计方面 你希望的是你设计的架构能有不同的技术(或者叫第三方组件)实现,你只需要通过在固定地方修改极少的代码便可以。
来个例子吧,假如现在有两个不同的技术,当然它们应该是在不同的程序集中的,只是为了方便把它们放在一起
/// <summary> /// 第三方组件A /// </summary> public class ModuleA { public void Say() { Console.WriteLine("it is ModuleA"); } } /// <summary> /// 第三方组件B /// </summary> public class ModuleB { public void Say() { Console.WriteLine("it is ModuleB"); } }
你希望你能应用任意其中一个,并且可以随意更改。你可以对外抽象出一个约束接口或者抽象类,下面我用的是接口,你可以在你的设计中,通过构造函数来引用
/// <summary> /// 接口 /// </summary> public interface IInterface { void Say();//接口约束必须实现这个方法 } public class BaseStyle { private IInterface module;//你并不知道也不关心当前用的是哪个组件,只要组件能实现这个接口就行 public BaseStyle(IInterface module)//能过构造函数引用接口 { this.module = module; } public void Say() { module.Say(); } }
通过属性引用
/// <summary> /// 通过属性引用组件方式 /// </summary> public class BaseStyle { public IInterface Module { get; set; } public void Say() { Module.Say(); } }
当你要应用任意一个组件时,只须要让它实现接口
public class ModuleA : IInterface { public void Say() { Console.WriteLine("it is ModuleA"); } }
这样就把BaseStyle类的Say方法分离出来,通过接口的实现类来完成。相当于接口的实现类可以是任意类。这便是传说中的接口分离,低藕合思想。例子不需要大,理解才是最重要。往大了说,这就相当于是面向接口编程。这是架构设计方面 。
然后就是应用了,也就是注入工作,Autofac之类的依赖注入组件不是必须的,只是当你的程序大了,用这些封装好的组件会更方便,易维护。你可以new BaseStyle然后传入对就的参数或设置属性就行了。
我一般用的是Autofac,用autofac,代码应该 是这样的
class Program { static void Main(string[] args) { ContainerBuilder builder = new ContainerBuilder(); builder.Register(o => new BaseStyle(o.Resolve<IInterface>()));//实例注入 builder.RegisterType<ModuleA>().As<IInterface>(); //类型注入 using (var container = builder.Build()) { BaseStyle bs = container.Resolve<BaseStyle>(); bs.Say(); } Console.ReadKey(); }
当然这样用肯定是没必要用autofac的,当有很多类须要用到Autofac注入时,这样并不会减少代码量,当要修改时,每个地方都要修改,如果只对Autofac停留在这个层面,还是不必要用它的好。
我比较喜欢的是封装一个Container类,由于我一惯喜欢用强类型,所以没有试过通过配置文件来配置。可能是因为我没有接触到真实项目的原因吧
封装一个类
public class ServiceContainer { private ServiceContainer() { }//不对外提供构造函数 private static IContainer container; /// <summary> /// 初始化container /// </summary> /// <param name="action"></param> public static void Initialize(Action<ContainerBuilder> action) { if(action!=null) { ContainerBuilder builder = new ContainerBuilder(); action(builder); container = builder.Build(); } } /// <summary> /// 封装一个不带参数的IContainer的方法 /// </summary> /// <typeparam name="Tservice"></typeparam> /// <returns>返回一个注入的服务类实例</returns> public static Tservice Resolve<Tservice>() { ThrowIfNotInitialized(); //检测容器是否初始化 return container.Resolve<Tservice>(); } //此处省略其它IContainer方法的封装 /// <summary> /// 检测容器是否初始化 /// </summary> private static void ThrowIfNotInitialized() { if (container == null) throw new InvalidOperationException("请先初始化容器,调用Initialize()方法"); } }
通过个类提供的静态初始化方法,可以在应用程序开始处,将所有要注入的依赖注入到容器中,然后你可以在程序的任意地方通过静态方法Resolve<T>方法从容器中取得你想要的具体依赖。这里我只封装了一个方法,还可以封装更多的静态方法,灵活调用。
最后再传上测试的所有代码。这里我抽象出了一些基类,设置好依赖注入,方便客户端调用时不需要传入参数或是设置属性,个人感觉应该比较完美了
using System; using Autofac; namespace AutofacDemo { class Program { static void Main(string[] args) { ServiceContainer.Initialize(o => { o.RegisterType<ModuleA>().As<IInterface>(); //o.RegisterType<ModuleB>().As<IInterface>();需要用其它实现时,只须要修改传入对应的类型 }); StyleA a = new StyleA();//纯净的客户端调用 StyleB b = new StyleB(); a.Say(); b.Say(); #region 基本注入 //ServiceContainer.Initialize(o => // { // o.RegisterType<ModuleA>().As<IInterface>(); // }); //StyleA a = new StyleA(ServiceContainer.Resolve<IInterface>()); //StyleB b = new StyleB(); //b.Module = ServiceContainer.Resolve<IInterface>(); //a.Say(); //b.Say(); #endregion #region 实例注入、属性注入 //ServiceContainer.Initialize(o => //{ // o.Register(c => new StyleA(c.Resolve<IInterface>())); //实例注入 // o.Register(c => new StyleB { Module = c.Resolve<IInterface>() });//属性注入 // o.RegisterType<ModuleA>().As<IInterface>(); //}); //StyleA a = ServiceContainer.Resolve<StyleA>(); //StyleB b = ServiceContainer.Resolve<StyleB>(); //a.Say(); b.Say(); #endregion Console.ReadKey(); } } /// <summary> /// 接口 /// </summary> public interface IInterface { void Say(); } /// <summary> /// 接口的某个实现类A,通常相当于第三方组件 /// </summary> public class ModuleA : IInterface { public void Say() { Console.WriteLine("it is ModuleA"); } } /// <summary> /// 接口的某个实现类B,通常相当于第三方组件 /// </summary> public class ModuleB : IInterface { public void Say() { Console.WriteLine("it is ModuleB"); } } public class BaseStyle { private IInterface module; public BaseStyle(IInterface module) { this.module = module; } public void Say() { module.Say(); } } /// <summary> /// 基类通过构造函数引用组件方式 /// </summary> public abstract class BaseStyleA { private IInterface module; protected BaseStyleA(IInterface module) { this.module = module; } public void Say() { module.Say(); } } /// <summary> /// 基类通过属性引用组件方式 /// </summary> public abstract class BaseStyleB { public virtual IInterface Module { get; set; } public void Say() { Module.Say(); } } public class StyleA:BaseStyleA { public StyleA(IInterface module) : base(module) { } public StyleA() : base(ServiceContainer.Resolve<IInterface>())//方便客户端调用时不需要传参 { } } public class StyleB:BaseStyleB { public override IInterface Module { get { return ServiceContainer.Resolve<IInterface>();//方便客户端调用时不需要设置属性 } } } }
记录对依赖注入的小小理解和autofac的简单封装的更多相关文章
- C# 一个初学者对 依赖注入 IOC 的理解( 含 Unity 的使用)
通过 人打电话 来谈谈自己对IOC的理解 版本1.0 public class Person { public AndroidPhone Phone { get; set; } public void ...
- 控制反转(IOC) 和依赖注入(DI) 的理解
1. IOC(控制反转) inverseof control是spring容器的内核,AOP.声明事务等功能在此基础上开花结果. 2. 通过实例理解IOC概念: 实例:<墨攻 ...
- 依赖注入和Guice理解
理解依赖注入,这篇文章写得非常好,结合spring的依赖注入分析的. http://blog.csdn.net/taijianyu/article/details/2338311/ 大体的意思是: 有 ...
- 【NetCore】依赖注入的一些理解与分享
依赖注入 DI 前言 声明:我是一个菜鸟,此文是自己的理解,可能正确,可能有误.仅供学习参考帮助理解,如果直接拷贝代码使用造成损失概不负责. 相关的文章很多,我就仅在代码层面描述我所理解的依赖注入是个 ...
- 依赖注入的方式测试ArrayList和LinkedList的效率(对依赖注入的再次理解)
9/20 号再进行学习 在C++中,main函数尽可能的简单,只要调用子函数的一句话就实现了功能. java开发中,controller就相同于是main函数,其他类的方法不在本类中时候, 1.可以用 ...
- 依赖注入(DI)和控制反转(IOC)的理解,写的太好了。
学习过spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...
- Spring学习-理解IOC和依赖注入
最近刚买了一本介绍ssm框架的书,里面主要对Mybatis.spring.springmvc和redis做了很多的讲解,个人觉得虽然有的内容我看不懂,但是整体上还是不错的.最近正在学习中,一边学习一边 ...
- 轻松学,浅析依赖倒置(DIP)、控制反转(IOC)和依赖注入(DI) 依赖注入和控制反转的理解,写的太好了。
轻松学,浅析依赖倒置(DIP).控制反转(IOC)和依赖注入(DI) 2017年07月13日 22:04:39 frank909 阅读数:14269更多 所属专栏: Java 反射基础知识与实战 ...
- 对spring控制反转以及依赖注入的理解
一.说到依赖注入(控制反转),先要理解什么是依赖. Spring 把相互协作的关系称为依赖关系.假如 A组件调用了 B组件的方法,我们可称A组件依赖于 B组件. 二.什么是依赖注入. 在传统的程序设计 ...
随机推荐
- 在mapreduce中做分布式缓存的问题
一.问题描述: 主要解决一个问题,就是两个表做join,两个表都够大,单个表都无法装入内存. 怎么做呢?思路就是对做join的字段做排序两个表都排序,然后针对一个表a逐行读取,希望能够在内存中加载到另 ...
- android-WebView
使用WebView 加载页面 一.加载页面 使用loadUrl() web资源:webView.loadUrl("http://www.baidu.com"); 本地文件用:web ...
- lua库函数
这些函数都是Lua编程语言的一部分, 点击这里了解更多. assert(value) - 检查一个值是否为非nil, 若不是则(如果在wow.exe打开调试命令)显示对话框以及输出错误调试信息 col ...
- 使用webbench对不同的web服务器进行压力测试
1.webbench在linux下的安装步骤,如果安装过程失败,请检查当前用户的执行权限,如果报找不到某个目录的错,请自行创建指定的目录: #wget http://home.tiscali.cz/~ ...
- zju(7)ADC操作实验
1.实验目的 1.学习和掌握S3C2410下ADC接口的操作方法以及应用程序的编写: 二.实验内容 1.编写EduKit-IV实验箱Linux操作系统下按键ADC的应用程序,并显示ADC的值. 三.主 ...
- 有效的PhoneGap CSS: WebKit Tap Highlight Color
原文链接:文章1:http://phonegap-tips.com/articles/essential-phonegap-css-webkit-tap-highlight-color.html(此文 ...
- mongo vue的常用操作
查找在某个范围内的记录: {"_id":{$in: [a,b,c]}} 如果images是个数组,则查询方式与普通数据一样:{"images":&quo ...
- c语言的输入输出函数
参考文章: http://blog.sina.com.cn/s/blog_784f40b80100psg9.html C语言输入输出函数分为两类: 1.格式化输入输出函数 2.非格式化输入输出 --- ...
- 【java基础学习】字符串
字符串 1. java内存区域(堆区.栈区.常量池) 2. String方法 获取长度 length(); 获取位置 indexOf(index); lastIndexOf(index) 获取子串 c ...
- 64位win10系统无法安装.Net framework3.5的解决方法
前言 Win10不会自带安装.net framework 3.5,而很多软件必须基于.net framework 3.5 sp1(例如:Sql Server 2014),从官网上下载的.net fra ...