Ninject依赖注入(一)
Ninject学习笔记(一)
理解依赖注入
DI概念
什么是DI?
DI是如何工作的?
什么是DI容器
使用Ninject
如何使用Ninject
Ninject对象生命周期
暂时范围
单例范围
线程范围
请求范围
自定义范围
Ninject模块
从xml配置依赖(Ninject XML扩展)
Ninject约定(Ninject Convention扩展)
选择程序集
选择组件
选择服务类型
绑定配置
理解依赖注入
DI概念
依赖注入,或者控制反转,降低代码耦合度。Ninject是一个轻量级.NET DI框架。
什么是DI?
一个例子,木匠伐木,需要工具斧子。
class Carpenter
{
Axe axe = new Axe();
void Lumber()
{
axe.Cut();
}
}
代码中,木匠依赖于斧子。此时需求变了,木匠买了木锯,那么上面的代码必须从新修改然后进行编译。再比如木匠比较爱惜工具,决定两种工具换着用,再比如,木匠决定提高生产率,购置了电锯等等。作为程序员来说,如果每次需求变更就重新编码,那么你会发现自己深陷沼泽地。
DI的出现就是为了解决这一问题的。它是一种编程方式,依赖关系不需要调用者来管理,统一由框架管理。“不要找我们,我们来找你”。
DI是如何工作的?
简简单单一句话——对接口编程,而不是对具体实现编程。用抽象元素来实现依赖,而不是具体类,如此一来我们可以很容易地替换具体的依赖类而不影响上层的调用组件。
class ITool
{
void Cut();
}
class Carpenter
{
private ITool tool;
void Carpenter(ITool tool)
{
tool = tool;
}
void Lumber()
{
tool.Cut();
}
}
什么是DI容器
DI容器是一个注入对象,用来向对象注入依赖性。一个应用中的依赖关系组成一个错综复杂的依赖图。DI容器就是来管理依赖复杂性的。它决定抽象类选择哪个实现类来实例化对象。Ninject有两种定义依赖的方式:
- xml配置:
<bind service="ITool
to="Axe"/> - 代码定义:`Bind().To()
使用Ninject
如何使用Ninject
- 在VS编辑环境中->右键项目->选择Nuget管理器->搜索Ninject->下载;
- 在项目中定义Kernel:
var kernel = new StandardKernel()
; - 通过
kernel.Get
方法获取依赖的对象。
Ninject对象生命周期
暂时范围
默认状态,Ninject不管理它创建的对象,也就是每次请求都new一个新对象。
单例范围
有两种方式创建单例
- 使用单例模式
class ConsoleLogger:ILogger
{
public static readonly ConsoleLogger Instance = new ConsoleLogger();
private static ConsoleLogger()
{
// Hiding constructor
}
public void Log(string message)
{
Console.WriteLine("{0}: {1}", DateTime.Now, message);
}
}
然后在Bind方法后调用ToConstant方法指定静态只读对象ConsoleLogger.Instance为常量对象。
kernel.Bind<ILogger>().ToConstant(ConsoleLogger.Instance);
使用InSingletonScope方法——更简单的方法
kernel.Bind<ILogger>().To<ConsoleLogger>().InSingletonScope();
指定某个类为单例
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 );
自定义范围是最灵活的,可以实现其他的范围:
- 线程范围:
kernel.Bind<object>().ToSelf().InScope( ctx => Thread.CurrentThread);
- 请求范围:
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配置文件格式如下:
<module name="moduleName">
<bind service="Namespace.IService1, AssemblyName"
to="Namespace.ConcreteService1, AssemblyName" />
<bind service="Namespace.IService2, AssemblyName"
to="Namespace.ConcreteService2, AssemblyName"
Scope="singleton"/>
</module>
加载XML文件到Kernel的方法:
kernel.Load("module1.xml","module2.xml","module3.xml");
可以使用相对输出路径的路径,也可以使用绝对路径,还可以使用通配符:
kernel.Load("Modules/*.xml);
Ninject约定(Ninject Convention扩展)
小的应用中,一个一个注册服务类型并不困难,但是一个有上百个服务的应用程序呢?约定配置允许我们绑定一组服务,而不是一个个分别绑定。
注册一个约定绑定需要三个步骤:选择包含具体类的程序集、选择程序集中的具体组件、选择具体组件相关的服务类型。
选择程序集
FromThisAssembly()
:选择包含当前代码的程序集;From(params Assembly[] assemblies)
:选择指定程序集;FromAssemblyContaining<SomeType>()
:选择包含指定类的程序集;Join()
:选择多个程序集。
kernel.Bind(x => x
.FromAssemblyContaining<CustomersService>()
.SelectAllClasses()
.Join()
.FromAssemblyContaining<MessageProvider>()
.SelectAllClasses()
.BindAllInterfaces());
默认情况下只有公有类型可以在程序集中被邦迪。为包含非公有类型,需要在选择程序集后显式调用IncludingNonePublicTypes
方法:
kernel.Bind(x => x
.FromAssemblyContaining<CustomersService>()
.IncludingNonePublicTypes()
.SelectAllClasses()
.BindAllInterfaces());
选择组件
选择要注册的组件。
SelectAllClasses()
:选择所有的非抽象类;Select(Func<Type, bool> filter)
:选择需要的类。
例子:选择以“Customer"开头的所有类:
kernel.Bind(r => r
.FromThisAssembly()
.Select(t =>t.Name.StartsWith("Customer"))
.BindBase());
例子:用条件对结果进行过滤:
kernel.Bind(x => x
.FromThisAssembly()
.SelectAllClasses()
.InNamespaces("Northwind.Controllers")
.BindBase());
选择服务类型
BindAllInterfaces()
: 绑定所有的选择的组件的接口到选择的组件。BindBase()
: 绑定选择的组件的基类型到当前的组件。BindDefaultInterface()
: 绑定指定类型的默认接口到类型。类型的默认接口跟类型同名。例如,ICustomerService是CutomerService的默认接口。BindDefaultInterfaces()
: 绑定指定类型的默认接口到类型。类型的默认接口是那些以类型的名字结尾的接口。例如,IRepository和ICustomerRepository都是SqlCustomerRepository的默认接口。BindSingleInterface()
: 要求指定类型只有一个接口。在这个情况下,这个接口绑定到这个类型。如果这个类型没有或者有多个接口,则不添加绑定。BindToSelf()
: 绑定类型到自身。BindSelection(ServiceSelector selector)
: 绑定选择的接口到类型。BindUsingRegex(string pattern)
: 绑定当前类型的符合正则表达式的接口到类型。
绑定配置
绑定创建后,可以像普通绑定的配置一样进行配置:
kernel.Bind(x => x
.FromThisAssembly()
.SelectAllClasses()
.BindAllInterfaces()
.Configure(b=>b.InSingletonScope()));
我们也可以使用ConfigureFor方法对某些类型分别进行配置。下面的例子,所有的repository类在构造函数中都注入"connectionString"参数,配置成单例生命周期。SqlCustomerRepository类重载成线程生命周期:
kernel.Bind(x => x
.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom<IRepository>()
.BindAllInterfaces()
.Configure(b =>b.InSingletonScope ()
.WithConstructorArgument("connectionString", ApplicationSettings.
ConnectionString))
.ConfigureFor<SqlCustomerRepository>(b =>b.InThreadScope()));
转载于:https://www.cnblogs.com/qianzi067/p/6594463.html
Ninject依赖注入(一)相关推荐
- Ninject依赖注入——构造函数、属性、方法和字段的注入(三)
1.Ninject简介 Ninject是基于.Net平台的依赖注入框架,它能够将应用程序分离成一个个高内聚.低耦合(loosely-coupled, highly-cohesive)的模块,然后以一种 ...
- 《Pro ASP.NET MVC 3 Framework》学习笔记之五【依赖注入及ninject工具使用】
一,创建松耦合的组件 1."分解关注点"是MVC模式里面一个非常重要的特性.我们想要在应用程序里面创建的组件尽可能的独立,这样我们就能管理比较少的依赖关系.理想情况下,每个组件都是 ...
- 依赖注入(DI)和Ninject,Ninject
我们所需要的是,在一个类内部,不通过创建对象的实例而能够获得某个实现了公开接口的对象的引用.这种"需要",就称为DI(依赖注入,Dependency Injection),和所谓的 ...
- 在MVC3项目中结合NInject实现依赖注入
解释: 依赖注入:(Dependency Injection),也称之为控制反转. 大致意思就是,让我们的应用程序所依赖的一些外部服务,可以根据需要动态注入,而不是预先在应用程序中明确的约束.这种思想 ...
- ASP.NET MVC3 + Ninject.Mvc3 依赖注入原来可以这么简单
第一步.新创建一个 ASP.NET MVC3 工程. 第二步.通过 NuGet 控制台直接输入命令:install-package Ninject.Mvc3 安装完这个源码包之后,所有的依赖注入框架已 ...
- [ASP.NET MVC 小牛之路]04 - 依赖注入(DI)和Ninject
特别提醒:本文编写时间是 2013 年,请根据目前 .NET 发展接收你所需的知识点. 为什么需要依赖注入 在[ASP.NET MVC 小牛之路]系列的理解MVC模式文章中,我们提到MVC的一个重要特 ...
- 依赖注入(DI)和Ninject
为什么需要依赖注入 在[ASP.NET MVC 小牛之路]系列的理解MVC模式文章中,我们提到MVC的一个重要特征是关注点分离(separation of concerns).我们希望应用程序的各部分 ...
- [转]解读ASP.NET 5 MVC6系列(7):依赖注入
本文转自:http://www.cnblogs.com/TomXu/p/4496440.html 在前面的章节(Middleware章节)中,我们提到了依赖注入功能(Dependency Inject ...
- [翻译]StructureMap 指南 – .NET中的依赖注入和控制反转
原文地址:http://www.pnpguidance.net/Post/StructureMapTutorialDependencyInjectionIoCNET.aspx StuctureMap ...
最新文章
- 宿主机訪问virtualBox中Ubuntu
- Java Annotation的RetentionPolicy介绍
- 在java中将数据信息写入文本中(2)
- mybatis mysql 分表_Mybatis的分表实战
- labuladong的算法小抄pdf_真漂亮!这份GitHub上爆火的算法面试笔记,助你圆满大厂梦...
- PAT_甲级_1002_C语言
- Kmplayer播放器 绿色免安装版 2016 中文版
- html5 webrtc fir 请求关键帧_中信建投官网强调认可我们的投资理念的股民朋友请求 CTRL D 收藏、锁定本直播地址...
- Android睡眠唤醒机制--Kernel态
- 欧盟网络安全局发布《供应链攻击威胁全景图》报告(中)
- [转载] 机器学习之主成分分析PCA(Python实现)
- 3dmax2020渲染器下载3dmax2020渲染器VRay4.2下载安装教程
- 基于springboot网上购物商城系统设计与实现
- angular2--使用JsBarcode生成条形码
- Java 大地坐标转经纬度,经纬度与WGS84坐标转换
- List把特定元素排在第一位
- Ajax的readyState和status
- 超微服务器双路主板系列,超微发布X12DPL系列服务器主板 支持双路10nm Ice Lake至强处理器...
- ios html5 app上架,H5封装的IOS应用上架App Store被拒怎么办
- Android 10(Q)GMS(cts/vts/gts)认证总结
热门文章
- mybaties与hibernate的不同点
- Karrigell 入门教程
- scala入门-10 隐式转换、隐式参数、隐式类
- java线程提交_从Java线程到线程池
- 字典生成工具_CANOpen系列教程09_CANOpen对象字典
- 模糊理论在机器人传感器中的应用_智能家电中的传感器应用大全
- linux华为路由器模拟器,华为路由器模拟器与实验内容.doc
- excel 公式 单引号 concat_Excel两个新函数帮你快速搞定批量连接
- 【JavaScript高级教程】JavaScript prototype(原型对象)
- linux c文件属性,【linux c learn 之stat】获取文件的属性