Ninject依赖注入(一)

Ninject学习笔记(一)

Ninject学习笔记(一)
理解依赖注入
DI概念
什么是DI?
DI是如何工作的?
什么是DI容器
使用Ninject
如何使用Ninject
Ninject对象生命周期
暂时范围
单例范围
线程范围
请求范围
自定义范围
Ninject模块
从xml配置依赖(Ninject XML扩展)
Ninject约定(Ninject Convention扩展)
选择程序集
选择组件
选择服务类型
绑定配置

理解依赖注入

DI概念

依赖注入,或者控制反转,降低代码耦合度。Ninject是一个轻量级.NET DI框架。

什么是DI?

一个例子,木匠伐木,需要工具斧子。

  1. class Carpenter
  2. {
  3. Axe axe = new Axe();
  4. void Lumber()
  5. {
  6. axe.Cut();
  7. }
  8. }

代码中,木匠依赖于斧子。此时需求变了,木匠买了木锯,那么上面的代码必须从新修改然后进行编译。再比如木匠比较爱惜工具,决定两种工具换着用,再比如,木匠决定提高生产率,购置了电锯等等。作为程序员来说,如果每次需求变更就重新编码,那么你会发现自己深陷沼泽地。

DI的出现就是为了解决这一问题的。它是一种编程方式,依赖关系不需要调用者来管理,统一由框架管理。“不要找我们,我们来找你”。

DI是如何工作的?

简简单单一句话——对接口编程,而不是对具体实现编程。用抽象元素来实现依赖,而不是具体类,如此一来我们可以很容易地替换具体的依赖类而不影响上层的调用组件。

  1. class ITool
  2. {
  3. void Cut();
  4. }
  5. class Carpenter
  6. {
  7. private ITool tool;
  8. void Carpenter(ITool tool)
  9. {
  10. tool = tool;
  11. }
  12. void Lumber()
  13. {
  14. tool.Cut();
  15. }
  16. }

什么是DI容器

DI容器是一个注入对象,用来向对象注入依赖性。一个应用中的依赖关系组成一个错综复杂的依赖图。DI容器就是来管理依赖复杂性的。它决定抽象类选择哪个实现类来实例化对象。Ninject有两种定义依赖的方式:

  1. xml配置:<bind service="ITool to="Axe"/>
  2. 代码定义:`Bind().To()

使用Ninject

如何使用Ninject

  1. 在VS编辑环境中->右键项目->选择Nuget管理器->搜索Ninject->下载;
  2. 在项目中定义Kernel:var kernel = new StandardKernel()
  3. 通过kernel.Get方法获取依赖的对象。

Ninject对象生命周期

暂时范围

默认状态,Ninject不管理它创建的对象,也就是每次请求都new一个新对象。

单例范围

有两种方式创建单例

  1. 使用单例模式
  1. class ConsoleLogger:ILogger
  2. {
  3. public static readonly ConsoleLogger Instance = new ConsoleLogger();
  4. private static ConsoleLogger()
  5. {
  6. // Hiding constructor
  7. }
  8. public void Log(string message)
  9. {
  10. Console.WriteLine("{0}: {1}", DateTime.Now, message);
  11. }
  12. }

然后在Bind方法后调用ToConstant方法指定静态只读对象ConsoleLogger.Instance为常量对象。
kernel.Bind<ILogger>().ToConstant(ConsoleLogger.Instance);

  1. 使用InSingletonScope方法——更简单的方法
    kernel.Bind<ILogger>().To<ConsoleLogger>().InSingletonScope();

  2. 指定某个类为单例
    kernel.Bind<ConsoleLogger>.ToSelf().InThreadScope();

线程范围

每一个线程只创建一个给定类型的对象。对象的生命周期和线程一样长。
kernel.Bind<object>().ToSelf().InThreadScope();

请求范围

用在Web应用程序中非常有用。在相同的请求范围内得到一个单例的对象。需要添加Ninject.Web.Common引用。
kernel.Bind<SampleClass>().ToSelf().InRequestScope();

自定义范围

自定义范围让我们定义我们自己的范围,在这个范围内保持一类型的唯一对象。只要提供的回调方法返回的对象引用是一样的,Ninject在这个范围内返回相同的实例。只要返回的对象引用变了,将创建一新的指定类型的对象。创建的对象实例将一直保存在缓存里,直到返回的范围对象被垃圾回收器回收。一旦范围对象被垃圾回收器回收,Ninject创建的所有的对象实例将被从缓存中释放和处理。
调用InScope方法传入Lamda表达式定义自定义返回:kernel.Bind<object>().ToSelf().InScope( ctx => User.Current );

自定义范围是最灵活的,可以实现其他的范围:

  1. 线程范围:kernel.Bind<object>().ToSelf().InScope( ctx => Thread.CurrentThread);
  2. 请求范围:kernel.Bind<object>().ToSelf().InScope( ctx => HttpContext.Current);

Ninject模块

如果应用程序规模比较大,那么注册的服务列表将会非常长,维护变得困难。一种好的方式是进行分组管理。Ninject提供了这个功能。每个组称为一个Ninject模块,只需要编写一个类实现INinjectModule接口,需要实现三个方法和两个属性。好消息是,Ninject还提供了一个实现该接口的抽象类NinjectModule,无需每次都实现接口的所有方法。
将多个模块加载到单个Ninject Kernel中的方法:
var kernel = new StandardKernel(new Module1(), new Module2(), ...)
也可以将应用程序中所有的模块同时加载到Ninject Kernel中:
kernel.Load(AppDomain.CurrentDomain.GetAssemblies());

从xml配置依赖(Ninject XML扩展)

需要Ninject XML扩展引用。注意记得发布xml文件时选择“Copy if newer”。
XML配置文件格式如下:

  1. <module name="moduleName">
  2.   <bind service="Namespace.IService1, AssemblyName"
  3.     to="Namespace.ConcreteService1, AssemblyName" />
  4.   <bind service="Namespace.IService2, AssemblyName"
  5.     to="Namespace.ConcreteService2, AssemblyName"
  6.     Scope="singleton"/>
  7. </module>

加载XML文件到Kernel的方法:
kernel.Load("module1.xml","module2.xml","module3.xml");
可以使用相对输出路径的路径,也可以使用绝对路径,还可以使用通配符:
kernel.Load("Modules/*.xml);

Ninject约定(Ninject Convention扩展)

小的应用中,一个一个注册服务类型并不困难,但是一个有上百个服务的应用程序呢?约定配置允许我们绑定一组服务,而不是一个个分别绑定。

注册一个约定绑定需要三个步骤:选择包含具体类的程序集、选择程序集中的具体组件、选择具体组件相关的服务类型。

选择程序集

  1. FromThisAssembly():选择包含当前代码的程序集;
  2. From(params Assembly[] assemblies):选择指定程序集;
  3. FromAssemblyContaining<SomeType>():选择包含指定类的程序集;
  4. Join():选择多个程序集。
  1. kernel.Bind(x => x
  2. .FromAssemblyContaining<CustomersService>()
  3. .SelectAllClasses()
  4. .Join()
  5. .FromAssemblyContaining<MessageProvider>()
  6. .SelectAllClasses()
  7. .BindAllInterfaces());

默认情况下只有公有类型可以在程序集中被邦迪。为包含非公有类型,需要在选择程序集后显式调用IncludingNonePublicTypes方法:

  1. kernel.Bind(x => x
  2. .FromAssemblyContaining<CustomersService>()
  3. .IncludingNonePublicTypes()
  4. .SelectAllClasses()
  5. .BindAllInterfaces());

选择组件

选择要注册的组件。

  1. SelectAllClasses():选择所有的非抽象类;
  2. Select(Func<Type, bool> filter):选择需要的类。
    例子:选择以“Customer"开头的所有类:
  1. kernel.Bind(r => r
  2. .FromThisAssembly()
  3. .Select(t =>t.Name.StartsWith("Customer"))
  4. .BindBase());

例子:用条件对结果进行过滤:

  1. kernel.Bind(x => x
  2. .FromThisAssembly()
  3. .SelectAllClasses()
  4. .InNamespaces("Northwind.Controllers")
  5. .BindBase());

选择服务类型

  • BindAllInterfaces(): 绑定所有的选择的组件的接口到选择的组件。
  • BindBase(): 绑定选择的组件的基类型到当前的组件。
  • BindDefaultInterface(): 绑定指定类型的默认接口到类型。类型的默认接口跟类型同名。例如,ICustomerService是CutomerService的默认接口。
  • BindDefaultInterfaces(): 绑定指定类型的默认接口到类型。类型的默认接口是那些以类型的名字结尾的接口。例如,IRepository和ICustomerRepository都是SqlCustomerRepository的默认接口。
  • BindSingleInterface(): 要求指定类型只有一个接口。在这个情况下,这个接口绑定到这个类型。如果这个类型没有或者有多个接口,则不添加绑定。
  • BindToSelf(): 绑定类型到自身。
  • BindSelection(ServiceSelector selector): 绑定选择的接口到类型。
  • BindUsingRegex(string pattern): 绑定当前类型的符合正则表达式的接口到类型。

绑定配置

绑定创建后,可以像普通绑定的配置一样进行配置:

  1. kernel.Bind(x => x
  2. .FromThisAssembly()
  3. .SelectAllClasses()
  4. .BindAllInterfaces()
  5. .Configure(b=>b.InSingletonScope()));

我们也可以使用ConfigureFor方法对某些类型分别进行配置。下面的例子,所有的repository类在构造函数中都注入"connectionString"参数,配置成单例生命周期。SqlCustomerRepository类重载成线程生命周期:

  1. kernel.Bind(x => x
  2. .FromThisAssembly()
  3. .SelectAllClasses()
  4. .InheritedFrom<IRepository>()
  5. .BindAllInterfaces()
  6. .Configure(b =>b.InSingletonScope ()
  7. .WithConstructorArgument("connectionString", ApplicationSettings.
  8. ConnectionString))
  9. .ConfigureFor<SqlCustomerRepository>(b =>b.InThreadScope()));


null


转载于:https://www.cnblogs.com/qianzi067/p/6594463.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372609.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我如何向团队解释依赖注入

最近&#xff0c;我们公司开始开发基于Java的新Web应用程序&#xff0c;经过一些评估过程&#xff0c;我们决定使用Spring。 但是许多团队成员并不了解Spring和Dependency Injection的原理。 因此&#xff0c;我被要求给出一个速成班&#xff0c;介绍什么是Spring上的依赖注入和…

可以添加自定义的Select控件

1.控件dom <select name"WebSiteTarget" id"WebSiteTarget" class"w1" onchange"editable2(this);"><option value"-1">请选择城市</option><option>福州</option><option>厦门</op…

innodb_io_capacity =innodb_lru_scan_depth*inoodb_buffer_pool_instances。与 checkpoint

innodb_lru_scan_depth:每个缓冲池刷脏页的能力 innodb_io_capacity: iops inoodb_buffer_pool_instances8 :缓冲池的个数 .关系&#xff1a; innodb_io_capacity > innodb_lru_scan_depth * inoodb_buffer_pool_instances 转载于:https://www.cnblogs.com/zengkefu/…

Java中的责任链模式

当应有几个处理器来执行某项操作并为这些处理器定义特定顺序时&#xff0c;就需要采用责任链设计模式。 在运行时处理器顺序的可变性也很重要。模式的UML表示如下&#xff1a; 处理程序定义处理器对象的一般结构。 这里的“ HandleRequest”是抽象处理器方法。 处理程序还具有自…

php的excel源码下载,PHPExcel-5 - 源码下载|Windows编程|其他小程序|源代码 - 源码中国...

文件名大小更新时间PHPExcel02019-05-11PHPExcel\.gitattributes702019-01-02PHPExcel\.gitignore1082019-01-02PHPExcel\.travis.yml5122019-01-02PHPExcel\16329.xlsx510662019-05-11PHPExcel\19093.xlsx511932019-05-11PHPExcel\43877.xlsx530952019-05-11PHPExcel\62045.xl…

使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(六)-- 依赖注入

本篇将介绍Asp.Net Core中一个非常重要的特性&#xff1a;依赖注入&#xff0c;并展示其简单用法。 第一部分、概念介绍 Dependency Injection&#xff1a;又称依赖注入&#xff0c;简称DI。在以前的开发方式中&#xff0c;层与层之间、类与类之间都是通过new一个对方的实例进行…

基于JAX-WS的webService开发实例

最近因为工作原因接触到webService&#xff0c;所以记录下开发中碰到的问题&#xff0c;方便自己以后复习&#xff0c;顺便发扬一下开源精神。刚刚接触webServie如果有什么错误欢迎大家指正。 本地环境&#xff1a;myEclipse10.6 tomcat7 JDK7 jaxws-ri-2.2.10 第一步&#xff…

完整的WebApplication JSF EJB JPA JAAS –第2部分

视图–创建和JSF设置 本教程是第1部分的继续。 让我们创建一个新的Dynamic Web Project 。 如下图所示创建它&#xff1a; 注意&#xff1a;在某些时候&#xff0c;Eclipse会询问您是否要添加JSF功能&#xff08;自动完成&#xff09;&#xff0c;然后启用它。 就像下面的屏幕…

lempel ziv matlab,基于Python的LempelZiv算法的熵估计

此函数允许估计时间序列的熵。它基于Lempel-Ziv压缩算法。对于长度为n的时间序列&#xff0c;熵估计为&#xff1a;E(1/n和L_i)^-1 ln(n)式中&#xff0c;L逯i是从位置i开始的最短子串的长度&#xff0c;该子串之前没有从位置1出现到i-1。当n接近无穷大时&#xff0c;估计的熵收…

Android使用绘图Path总结

Path作为Android中一种相对复杂的绘图方式&#xff0c;官方文档中的有些解释并不是很好理解&#xff0c;这里作一个相对全面一些的总结&#xff0c;供日后查看&#xff0c;也分享给大家&#xff0c;共同进步。 1.基本绘图方法 addArc(RectF oval, float startAngle, float swee…

2017.3.23下午

下午通过对OSPF基本原理进一步的学习&#xff0c;对上午学习的内容进行了复习。 转载于:https://www.cnblogs.com/bgd140206206/p/6606192.html

编写Eclipse插件教程–第1部分

Eclipse是三个最受欢迎的Java开发IDE之一。 其成功的原因之一是其可扩展性。 对于任何知道该怎么做并且已经做到的人来说&#xff0c;编写eclipse插件都可以非常轻松快捷。 不幸的是&#xff0c;第一次在Eclipse中进行操作可能会非常耗时且令人沮丧。 Eclipse框架非常庞大&…

简单Window下 Android Studio的安装

&#xff08;1&#xff09;首先安装JDK 下载JDK 本人觉得官方网站下JDK比较慢&#xff0c;可以直接百度JDK&#xff0c;&#xff08;如果是64位 百度搜索记得64位&#xff09; 类似于这样的下载 安装可以看下教程&#xff0c;包括环境变量的配置 如何安装JDK &#xff08;2&…

日期处理一之NSLalendar的使用

一、日期和时间模式 日期和时间格式由日期和时间模式字符串组成&#xff0c;在日期和时间模式字符串中未加引号的A到‘Z’和a到‘z’被解释为模式字母&#xff0c;用来表示日期或时间。字符串元素&#xff0c;文本可以使用单引号&#xff08;‘’&#xff09;引起来使用。定义以…

java的使用Pair要导入什么包,第三方jar包的使用

被导入的外部类所在源文件通常要打包成jar包&#xff0c;java中的jar文件装的是 .class 文件。它是一种压缩格式和zip兼容&#xff0c;被称为jar包。JDK提供的许多类&#xff0c;也是以jar包的形式提供的。在用的时候呢&#xff0c;你的文件里有很多个类&#xff0c;把这些类和…

十大最受欢迎的新Eclipse插件

Eclipse Marketplace仍然是发现有趣且相关的Eclipse插件的地方。 通过Eclipse Marketplace客户端&#xff0c;每月成功安装100,000多个基于Eclipse的产品。 我们提供了过去30天 以来所有时间最受欢迎的插件列表。 我认为看看过去12个月中最受欢迎的新插件会很有趣。 以下列出了…

在桌面显示我电脑

打开Windows PowerShell&#xff08;一个像是命令提示符的东西[蓝底白字]&#xff0c;但不是命令提示符&#xff09;&#xff0c;在Windows PowerShell内输入cmd回车&#xff0c;当返回如下信息&#xff1a; Microsoft Windows [版本 6.2.9200](c) 2012 Microsoft Corporation。…

《Java技术》第二次作业计科1501赵健宇

&#xff08;一&#xff09;学习总结 1.使用Eclipse关联jdk源代码,查看String类的equals&#xff08;&#xff09;方法 equals&#xff08;&#xff09;方法截图 “”比较的是地址。equals方法他同样使用号进行内存地址的比较。但是equals方法重写如果号比较不相等&#xff0c;…

注射php,UPDATE注射(mysqlphp)的两个模式

一.测试环境&#xff1a;OS:Windowsxpsp2php:php4.3.10(mysql4.1.9apache1.3.33二.测试数据库结构&#xff1a;-----start-----数据库:test----------------------------------------------------------------表的结构userinfo--CREATETABLEuserinfo(groudidvarchar(12)NOTNULL…

JUnit的内置Hamcrest Core Matcher支持

在用JUnit和Hamcrest改进assertEquals的文章中&#xff0c;我简要讨论了Hamcrest “ 核心 ”匹配器与JUnit的现代版本“结合”在一起的情况。 在那篇文章中&#xff0c;我特别关注了JUnit的assertThat&#xff08;T&#xff0c;Matcher&#xff09;静态方法与Hamcrest核心is()匹…