使用Ninject的一般步骤
以下为DI控制反转个人理解烦请各位大牛指教~
编写程序时我们应当遵循抵耦合高内聚的原则(各个功能模块互不依赖).
我们可以利用面向对象里面接口的特性来进行DI控制反转,让功能模块全部依赖接口,而不依赖具体的实现类,当程序跑起来以后通过注入的方式注入具体的实现类如以下代码:
/// <summary>
/// 购物车类
/// </summary>
public class ShoppingCart {
/// <summary>
/// 创建计算器接口
/// </summary>
IvalueCalculator calculator; /// <summary>
/// 构造函数来注入实际调用的计算方法
/// </summary>
/// <param name="ivalueCalculator"></param>
public ShoppingCart(IvalueCalculator ivalueCalculator)
{
calculator = ivalueCalculator;
} /// <summary>
/// 价格计算
/// </summary>
/// <returns></returns>
public decimal CalculateStockValue()
{
Product[] products = {
new Product {Name = "西瓜", Category = "水果", Price = 2.3M},
new Product {Name = "苹果", Category = "水果", Price = 4.9M},
new Product {Name = "空心菜", Category = "蔬菜", Price = 2.2M},
new Product {Name = "地瓜", Category = "蔬菜", Price = 1.9M}
};
decimal totalValue = calculator.ValueProducts(products);
return totalValue;
} } /// <summary>
/// 计算器实现类
/// </summary>
public class LinqValueCalculator : IvalueCalculator
{
/// <summary>
/// 价格计算实现方法
/// </summary>
/// <param name="products"></param>
/// <returns></returns>
public decimal ValueProducts(params Product[] products)
{
return products.Sum(u => u.Price);
} } /// <summary>
/// 计算器接口
/// </summary>
public interface IvalueCalculator
{
/// <summary>
/// 价格计算方法
/// </summary>
/// <param name="products"></param>
/// <returns></returns>
decimal ValueProducts(params Product[] products);
}
这样,购物车类就实现了松耦合,购物车内的计算价格方法只依赖于计算器接口(IvalueCalculator ),而不依赖具体的计算类(LinqValueCalculator),实际的价格计算类我们通过构造函数的方法注入到购物车内的计算器接口
当我们在实际使用时既可以像如下方法一样实现
static void Main(string[] args)
{
//创建一个接口的对象,引用计算类
IvalueCalculator calculator = new LinqValueCalculator();
//以方法传入具体实现类
ShoppingCart shopping = new ShoppingCart(calculator);
//调用
Console.WriteLine("价格:{0}", shopping.CalculateStockValue());
Console.ReadLine();
}
可以通过C#的 Ninject 来管理各种注入,只需要提前绑定好接口的对应实现类既可以在使用时去索要一个对应的实现类,如下代码
//Ninject
IKernel ninjectKernel = new StandardKernel();
//把一个接口(IValueCalculator)绑定到一个实现该接口的类(LinqValueCalculator)
ninjectKernel.Bind<IvalueCalculator>().To<LinqValueCalculator>(); //向NiNject索要一个IvalueCalculator的实现类
IvalueCalculator calcImpl = ninjectKernel.Get<IvalueCalculator>();
//注入购物车类
ShoppingCart shopping = new ShoppingCart(calcImpl); Console.WriteLine("价格:{0}", shopping.CalculateStockValue());
Console.ReadLine();
知识点1:并且,如果你的价格计算实现类(LinqValueCalculator)的内部调用了其它接口,那么Ninject会自动帮你注入要调用接口的实现类(前提是这个调用的接口在之前已经绑定了实现类)
例如:创建一个打折接口(IDiscountHelper),再创建一个类来实现一个默认打折方法(DefaultDiscountHelper)
/// <summary>
/// 折扣计算接口
/// </summary>
public interface IDiscountHelper {
decimal ApplyDiscount(decimal totalParam);
} /// <summary>
/// 默认折扣计算接口
/// </summary>
public class DefaultDiscountHelper : IDiscountHelper
{
/// <summary>
/// 折扣结算方法
/// </summary>
/// <param name="totalParam"></param>
/// <returns></returns>
public decimal ApplyDiscount(decimal totalParam)
{
return (totalParam - (1m / 10m * totalParam));
}
}
在价格计算实现类(LinqValueCalculator)内调用打折接口(IDiscountHelper)
/// <summary>
/// 计算器实现类
/// </summary>
public class LinqValueCalculator : IvalueCalculator
{
/// <summary>
/// 定义一个打折接口
/// </summary>
private IDiscountHelper discount; /// <summary>
/// 用构造函数注入打折类
/// </summary>
/// <param name="discountHelper"></param>
public LinqValueCalculator(IDiscountHelper discountHelper) {
discount = discountHelper;
} /// <summary>
/// 价格计算实现方法
/// </summary>
/// <param name="products"></param>
/// <returns></returns>
public decimal ValueProducts(params Product[] products)
{
//调用打折接口的实现类 来计算价格
return discount.ApplyDiscount(products.Sum(u => u.Price));
} }
那么当我们在调用价格计算类(LinqValueCalculator)时,Ninject会自动帮我们注入打折实现类(DefaultDiscountHelper)
(注:前提是,打折接口(IDiscountHelper)你在之前已经用Ninject绑定了它的实现类打折实现类(DefaultDiscountHelper))
//Ninject
IKernel ninjectKernel = new StandardKernel();
//把一个接口(IValueCalculator)绑定到一个实现该接口的类(LinqValueCalculator)
ninjectKernel.Bind<IvalueCalculator>().To<LinqValueCalculator>(); //给折扣接口绑定一个默认的打折类
ninjectKernel.Bind<IDiscountHelper>().To<DefaultDiscountHelper>(); //向NiNject索要一个IvalueCalculator的实现类
IvalueCalculator calcImpl = ninjectKernel.Get<IvalueCalculator>(); //注意:价格计算类(LinqValueCalculator)类里面有一个折扣接口(IDiscountHelper),折扣接口需要一个具体的折扣类(DefaultDiscountHelper),
//我这里在向 ninjectKernel.Get<IvalueCalculator>() 请求价格计算类(LinqValueCalculator类里面有一个折扣接口)的时候并没有传入折扣实现类
//是ninject自己帮我完成了.
//原理就是在上面我们给打折接口(IDiscountHelper)绑定了一个默认的打折实现类(DefaultDiscountHelper),ninject检测到我们绑定了默认打折实现类(DefaultDiscountHelper),所以自动邦我们补全了; //注入购物车类
ShoppingCart shopping = new ShoppingCart(calcImpl); Console.WriteLine("价格:{0}", shopping.CalculateStockValue());
Console.ReadLine();
知识点2:现在我们的打折实现类(DefaultDiscountHelper)内的折扣力度是写死的,如果我们想让折扣力度由外部传入该肿么办呢?
/// <summary>
/// 默认折扣计算接口
/// </summary>
public class DefaultDiscountHelper : IDiscountHelper
{
/// <summary>
/// 默认折扣类的打折力度
/// </summary>
public decimal DiscountSize { get; set; } /// <summary>
/// 折扣结算方法
/// </summary>
/// <param name="totalParam"></param>
/// <returns></returns>
public decimal ApplyDiscount(decimal totalParam)
{
return (totalParam - (DiscountSize / 10m * totalParam));
}
}
在NinJect注入具体实现类时,我们可以通过下面的形式对打折力度进去传入
Ninject核心对象.Bind<绑定的接口>().To<要绑定的实现类>().WithPropertyValue("实现类内部属性的名称",实现类内部属性的值);
//Ninject
IKernel ninjectKernel = new StandardKernel();
//把一个接口(IValueCalculator)绑定到一个实现该接口的类(LinqValueCalculator)
ninjectKernel.Bind<IvalueCalculator>().To<LinqValueCalculator>(); //给折扣接口绑定一个默认的打折类
ninjectKernel.Bind<IDiscountHelper>().To<DefaultDiscountHelper>().WithPropertyValue("DiscountSize", 5M); //向NiNject索要一个IvalueCalculator的实现类
IvalueCalculator calcImpl = ninjectKernel.Get<IvalueCalculator>(); .......
如果要给多个属性赋值,则可以在Bind和To方式后添加多个WithPropertyValue(<属性名>,<属性值>)方法。
同样的我们也可以以形参的形式传入
/// <summary>
/// 默认折扣计算接口
/// </summary>
public class DefaultDiscountHelper : IDiscountHelper
{
public DefaultDiscountHelper(decimal discountSize)
{
DiscountSize = discountSize;
} /// <summary>
/// 默认折扣类的打折力度
/// </summary>
public decimal DiscountSize { get; set; } /// <summary>
/// 折扣结算方法
/// </summary>
/// <param name="totalParam"></param>
/// <returns></returns>
public decimal ApplyDiscount(decimal totalParam)
{
return (totalParam - (DiscountSize / 10m * totalParam));
}
}
此时在注入实现类时改为
Ninject核心对象.Bind<绑定的接口>().To<要绑定的实现类>().WithConstructorArgument("形参的名称",形参的值);
调用方法改为
//把一个接口(IValueCalculator)绑定到一个实现该接口的类(LinqValueCalculator)
ninjectKernel.Bind<IvalueCalculator>().To<LinqValueCalculator>(); //给折扣接口绑定一个默认的打折类
ninjectKernel.Bind<IDiscountHelper>().To<DefaultDiscountHelper>().WithConstructorArgument("discountSize",10M); //向NiNject索要一个IvalueCalculator的实现类
IvalueCalculator calcImpl = ninjectKernel.Get<IvalueCalculator>();
如果构造函数存在多个形参那么在每一个后面在.WithConstructorArgument 即可
例如:
Ninject核心对象.Bind<绑定的接口>().To<要绑定的实现类>().WithConstructorArgument("形参的名称",形参的值).WithConstructorArgument("形参的名称1",形参的值1).WithConstructorArgument("形参的名称2",形参的值2);
知识点3:在对接口进行绑定时我们都是通过如下方法绑定
//向NiNject索要一个IvalueCalculator的实现类
IvalueCalculator calcImpl = ninjectKernel.Get<IvalueCalculator>(); //把要到的实现类注入到购物车类内部
ShoppingCart shopping = new ShoppingCart(calcImpl);
转换为中文意为:
由计算(IvalueCalculator) 接口 calcImpl 向 ninjectKernel 索要一个(计算接口)IvalueCalculator的具体实现类(LinqValueCalculator)(具体实现类由上面接口绑定而得)的引用;
创建一个(购物车类)ShoppingCart shopping ,指向(购物车)ShoppingCart类并且由构造函数注入前面从ninjectKernel获得的计算接口(IvalueCalculator)的实现类(LinqValueCalculator);
这样写我个人觉得最通俗易懂,但是不够简洁,Ninject还有另外一种更简单的获取实现类的方法
ninjectKernel.Bind<IvalueCalculator>().To<LinqValueCalculator>();
//给折扣接口绑定一个默认的打折类
ninjectKernel.Bind<IDiscountHelper>().To<DefaultDiscountHelper>().WithConstructorArgument("discountSize",5M);//标识自我绑定
ninjectKernel.Bind<ShoppingCart>().ToSelf();
//注入购物车类
ShoppingCart shopping = ninjectKernel.Get<ShoppingCart>();
由知识点1可知: Ninject 不仅可以 以 接口 绑定 实现类 的 形式 进行 绑定,也可以进行具体类绑定具体类的操作;
这是自我绑定方法,再由上方知识点可推断 当我们要调用的类需要一个接口的实现类时,如果这个接口是在之前已经进行绑定过的,那么Ninject会自动邦我们进行注入
也就是说:
购物车(ShoppingCart)类先进行绑定,它绑定的实现类就是他自己,所有通过Ninject请求购物车(ShoppingCart)类的请求都会返回一个购物车(ShoppingCart)类自己,再因为 已经在Ninject绑定的接口在被调用时都会自动邦我们进行注入操作
(购物车类内部有一个计算接口(IvalueCalculator)计算接口需要一个计算实现类(LinqValueCalculator) 而计算接口在之前我们已经进行了绑定,所以Ninject会自动帮我们进行注入)
最核心的就是要明白,Ninject会对所有已经绑定过的接口进行自动注入实现类的操作.(貌似有一定的递归逻辑?)
这样整个自绑定逻辑就已经缕清楚了~
由"Liam Wang"编写的"[ASP.NET MVC 小牛之路]04 - 依赖注入(DI)和Ninject"整理而成
URL:https://www.cnblogs.com/willick/p/3223042.html
使用Ninject的一般步骤的更多相关文章
- [ASP.NET MVC 小牛之路]04 - 依赖注入(DI)和Ninject
本人博客已转移至:http://www.exblr.com/liam 为什么需要依赖注入 在[ASP.NET MVC 小牛之路]系列的理解MVC模式文章中,我们提到MVC的一个重要特征是关注点分离( ...
- [ASP.NET MVC 小牛之路]05 - 使用 Ninject
在[ASP.NET MVC 小牛之路]系列上一篇文章(依赖注入(DI)和Ninject)的末尾提到了在ASP.NET MVC中使用Ninject要做的两件事情,续这篇文章之后,本文将用一个实际的示例来 ...
- C#Console程序使用Ninject
本来想使用一下Ninject的,然后搜索了很久,都没找到比较详细的关于Ninject的使用方法等内容.于是乎干脆自己来写几篇介绍Ninject的内容. 1. 依赖注入和IOC 依赖注入和IO ...
- ASP.NET MVC中使用Ninject
ASP.NET MVC中使用Ninject 在[ASP.NET MVC 小牛之路]系列上一篇文章(依赖注入(DI)和Ninject)的末尾提到了在ASP.NET MVC中使用Ninject要做的两件事 ...
- 依赖注入(DI)和Ninject
[ASP.NET MVC 小牛之路]04 - 依赖注入(DI)和Ninject 本文目录: 1.为什么需要依赖注入 2.什么是依赖注入 3.使用NuGet安装库 4.使用Ninject的一般步骤 5. ...
- [1] Ninject
为什么使用这种依赖注入的框架呢?我借鉴两张图做一下说明 传统的接口方式,即 IValueCalculator I=new LinqValueCalculator,虽然用接口做的隔离,但是在调用的时候实 ...
- 依赖注入框架Ninject
为什么需要依赖注入 我们提到MVC的一个重要特征是关注点分离(separation of concerns).我们希望应用程序的各部分组件尽可能多的相互独立.尽可能少的相互依赖. 我们的理想情况是:一 ...
- 使用 Ninject
在[ASP.NET MVC 小牛之路]系列上一篇文章(依赖注入(DI)和Ninject)的末尾提到了在ASP.NET MVC中使用Ninject要做的两件事情,续这篇文章之后,本文将用一个实际的示例来 ...
- [ASP.NET MVC 小牛之路]05 - 使用 Ninject实现依赖注入
在[ASP.NET MVC 小牛之路]系列上一篇文章(依赖注入(DI)和Ninject)的末尾提到了在ASP.NET MVC中使用Ninject要做的两件事情,续这篇文章之后,本文将用一个实际的示例来 ...
随机推荐
- CSS学习笔记二:css 画立体图形
继上一次学了如何去运用css画平面图形,这一次学如何去画正方体,从2D向着3D学习,虽然有点满,但总是一个过程,一点一点积累,然后记录起来. Transfrom3D 在这一次中运用到了一下几种属性: ...
- Tiny4412之外部中断
一:外部中断 在之前我们学习按键驱动的时候,我们检测按键有没有按下是通过轮循的方式(也就是我们说的死循环),这样虽然可以检测实现按键,但太浪费系统资源了,不论我们按键中断有没有发生,cpu都要一直进行 ...
- 【转】利用 force index优化sql语句性能
今天写了一个统计sql,在一个近亿条数据的表上执行,200s都查不出结果.SQL如下: select customer,count(1) c from upv_** where created bet ...
- BigDecimal 专题
//****BigDecimal中传入的double类型的数据,要为String类型,不然得到在BigDecimal仍然是不准确的double数据**** // BigDecimal addend = ...
- Node.js 专题
前提电脑中已经安装过NodeJS, npm.现在需要进行升级操作.1.查看当前的npm和NodeJs的版本: C:\Users\Administrator>node -v v4.4.3 C:\U ...
- 理解主从设备模式(Master-Slave)
前言 在给定上下文的软件体系结构中,为了解决某些经常出现的问题而形成的通用且可重用的解决方案称之为架构模式,而常见的体系架构模式主要有以下十种 分层模式 客户端-服务器模式 主从设备模式 管道-过滤器 ...
- Selenium库,Python精品教程!
什么是Selenium selenium基本使用 用python写爬虫的时候,主要用的是selenium的Webdriver,我们可以通过下面的方式先看看Selenium.Webdriver支持哪些浏 ...
- QM1_Time value of Money
总体框架 Time Value Interest Rate rf: 无风险收益率 (CFA中一般认为是美国短期国债T-bill的收益率) Nominal risk-free rate: 名义无风险税 ...
- Java 学习笔记 (四) Java 语句优化
这个问题是从headfirst java看到的. 需求: 一个移动电话用的java通讯簿管理系统,要求最有效率的内存使用方法. 下面两段程序的优缺点,哪个占用内存更少. 第一段: Contact[]c ...
- MySQL基本命令1
在ubuntu系统中操作命令:登录:mysql -uroot -p启动:service mysql start停止:service mysql stop重启:service mysql restart ...