Ninject简介(转)
1.为什么要用Ninject?
Ninject是一个IOC容器用来解决程序中组件的耦合问题,它的目的在于做到最少配置。其他的的IOC工具过于依赖配置文件,需要使用assembly-qualified名称来进行定义,庸长且复杂常常因为打错字而破坏程序。这些是他的优点,也是为什么要选择它。Ninject同时不能进行热插拔。
2.Ninject做些什么?
其实Ninject做的事情很简单,说白了就是为我们选择一个想要的类来处理事务。来看下面的简单的例子。
public class Product
{
public int ProductID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
} public interface IValueCalculater
{
decimal ValueProducts(params Product[] products);
} public class LinqValueCalculator : IValueCalculater
{
public decimal ValueProducts(params Product[] products)
{
return products.Sum(p => p.Price);
}
}
我们定义了一个实体类,一个接口,一个实现接口的类,这个类完成的功能是计算总价。
public class ShoppingCart
{
protected IValueCalculater calculator;
protected Product[] products; public ShoppingCart(IValueCalculater calcuParam)
{
this.calculator = calcuParam;
products = new[]{
new Product(){Name="Kayak" , Price=275M},
new Product(){Name="Lifejacket" , Price=48.95M},
new Product(){Name="Scooceer ball" , Price=19.5M},
new Product(){Name="Stadium" , Price=79550M}
};
} public virtual decimal CalculatStockValue()
{
decimal totalPrice = calculator.ValueProducts(products);
return totalPrice;
}
}
ShopingCart类的构造函数使用接口IValueCalculater实现作为一个准备DI的参数。CalculatStockValue方法创建一个Product对象数组,然后调用IValueCalculater接口中的ValueProducts来获得总价。这里可以看到ShoppingCart类中只出现了接口IValueCalculater,却没有出现这个接口的实现类LinqValueCalculator,说的直白点就是ShoppingCart中计算的总价是一个影藏的类实现的,我们可以修改这个影藏的类达到修改总价的目的,而不需要修改ShoppingCart类中的代码。好的,Ninject做的工作就是和上面的类似,是的,它只能完成这么个工作,不过会有很多的变化,最终目的只有一个,就是决定到当前到底要使用哪一个类似LinqValueCalculator着那个的实现类。
3.Ninject的使用
关于如何下载安装Ninject这里不再说了,网上有很多的资源。这里只说几个简单的例子。
IKernel ninjectKernel = new StandardKernel();
ninjectKernel.Bind<IValueCalculater>().To<LinqValueCalculator>();
上面的代码将想使用的类型和他的接口进行绑定,高祖Ninject,当接收到一个实现IValueCalculater的请求的时候,创建病返回LinqValueCalculator这个类,上面的两个关键字Bind,To可以帮助我们理解他的意思。
IValueCalculater calcImpl = ninjectKernel.Get<IValueCalculater>();
ShoppingCart cart = new ShoppingCart(calcImpl);
当我们调用上面两句的时候就会去计算总价。
下面我们看看他的变形。
1.依赖性链
当使用ninjectKernel.Get创建一个类型的时候会检查这个类型与其他类型之间的耦合,如果有额外的依赖性,Ninject会解析这些依赖性,并创建所需要的所有的类的类型。下面我们在LinqValueCalculator中再次依赖其他的类型。
public interface IDiscountHelper
{
decimal ApplyDiscount(decimal totalParam);
} public class DefalutDiscountHelper : IDiscountHelper
{
private decimal discountRate; public DefalutDiscountHelper(decimal discountParam)
{
discountRate = discountParam;
} public decimal ApplyDiscount(decimal totalParam)
{
return (totalParam - (discountRate / 100M * totalParam));
}
} public class LinqValueCalculator : IValueCalculater
{
IDiscountHelper discounter; public LinqValueCalculator(IDiscountHelper discountParam)
{
discounter = discountParam;
} public decimal ValueProducts(params Product[] products)
{
return discounter.ApplyDiscount(products.Sum(p => p.Price));
}
}
和IValueCalculator所做的那样我们把IDiscountHelper和DefalutDiscountHelper 关联起来。
ninjectKernel.Bind<IDiscountHelper>().To<DefalutDiscountHelper>();
IValueCalculater calcImpl = ninjectKernel.Get<IValueCalculater>();
当IValueCalculater被请求的时候,Ninject知道它要实例化的是LinqValueCalculator,然后进一步考察这个类,并发现他依赖一个可以解析的接口,Ninject会创建DefaultDiscountHelper的一个实例,并把它注入到LinqValueCalculator类的构造器中,一IValueCalculator作为返回结果,不管这个依赖性链有多长,多复杂,Ninject都会以这种方式检查它要实例化的每一个依赖性。
2.指定属性和参数值
修改DefalutDiscountHelper 类如下
public class DefalutDiscountHelper : IDiscountHelper
{
private decimal discountRate; public decimal DiscountSize { get; set; } public decimal ApplyDiscount(decimal totalParam)
{
return (totalParam - (DiscountSize / 100M * totalParam));
}
}
在使用Ninject将具体类绑定到类型的时候,我已使用WithPropertyValue方法来设置DefalutDiscountHelper 类中的属性DiscountSize,方法如下
ninjectKernel.Bind<IDiscountHelper>().To<DefalutDiscountHelper>()
.WithPropertyValue("DiscountSize", 50M);
IValueCalculater calcImpl = ninjectKernel.Get<IValueCalculater>();
3.指定构造函数的参数值
如果具体类中有带参数的构造函数可以使用WithConstructorArgument方法来指定这个参数,修改DefalutDiscountHelper如下
public class DefalutDiscountHelper : IDiscountHelper
{
private decimal discountRate; public decimal DiscountSize { get; set; } public DefalutDiscountHelper(decimal discountParam)
{
discountRate = discountParam;
} public decimal ApplyDiscount(decimal totalParam)
{
return (totalParam - (discountRate / 100M * totalParam));
}
}
使用Ninject绑定如下:
ninjectKernel.Bind<IDiscountHelper>().To<DefalutDiscountHelper>()
.WithConstructorArgument("discountParam", 50M);
IValueCalculater calcImpl = ninjectKernel.Get<IValueCalculater>();
4.上面我们都是绑定接口,其实只要是有继承关系的两个类之间也可以进行绑定,下面我们来看一个例子,我们先顶一个ShoppingCart类,然后定义一个LimitShoppingCart类来继承它,代码如下:
public class ShoppingCart
{
protected IValueCalculater calculator;
protected Product[] products; public ShoppingCart(IValueCalculater calcuParam)
{
this.calculator = calcuParam;
products = new[]{
new Product(){Name="Kayak" , Price=275M},
new Product(){Name="Lifejacket" , Price=48.95M},
new Product(){Name="Scooceer ball" , Price=19.5M},
new Product(){Name="Stadium" , Price=79550M}
};
} public virtual decimal CalculatStockValue()
{
decimal totalPrice = calculator.ValueProducts(products);
return totalPrice;
}
}
public class LimitShoppingCart : ShoppingCart
{
public decimal ItemLimit { get; set; } public LimitShoppingCart(IValueCalculater calcParm)
: base(calcParm)
{ } public override decimal CalculatStockValue()
{
var filteredProducts = products.Where(e => e.Price < ItemLimit);
return calculator.ValueProducts(filteredProducts.ToArray());
}
}
下面的代码将子类绑定到它的父类上,代码如下:
ninjectKernel.Bind<ShoppingCart>().To<LimitShoppingCart>().WithPropertyValue("ItemLimit",200M);
ShoppingCart cart = ninjectKernel.Get<LimitShoppingCart>();
5.使用条件绑定
可以使用Ninject绑定同一个接口的多个实现,或同一个类的多个派生类,并在不同条件下绑定不同的类。我们可以对当前绑定的具体类进行判断,最终绑定另外一个具体类,先来定义一个IValueCalculator的另外一个实现类,代码如下
public decimal ValueProducts(params Product[] products)
{
decimal totalValue = 0; foreach (Product p in products)
{
totalValue += p.Price;
}
return totalValue;
}
下面的代码将有选择的创建Ninject类。
ninjectKernel.Bind<IValueCalculater>().To<IterativeValueCalculatgor>().WhenInjectedInto<LimitShoppingCart>();
这段代码的意思是当LimitShoppingCart这个类被绑定的时候才将IterativeValueCalculatgor绑定到它的接口中,我们可以将IterativeValueCalculatgor和LimitShoppingCart看做是一套具体的逻辑,是有具体关系的,例如这是同一次促销的产品,即他们是为同一此促销活动而新建的类,这就为我们的业务逻辑实现提供一个便利。
3.将Ninject用于ASP.NET MVC
这部分本人还没有用到过,是从书本中看到的,也是初次接触。DefaultControllerFactory类是创建控制器类实例的一个类。先看代码吧。
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel ninjectKernel; public NinjectControllerFactory()
{
ninjectKernel = new StandardKernel();
AddBindings();
} private void AddBindings()
{
ninjectKernel.Bind<IValueCalculater>().To<LinqValueCalculator>();
} protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
return controllerType == null ? null : (IController)ninjectKernel.Get(controllerType);
}
}
这个类创建了一个Ninject内核,用它对控制器类的请求进行服务,请求是通过GetControllerInstance方法实现的,它是在MVC框架在需要一个控制器对象时调用的。我们不需要明确的绑定控制器,可以依靠默认的自身绑定特性,因为控制器是从System.Web.Mvc.Controller派生来的具体类。
AddBinding方法允许我们队存储库和希望保持送耦合的组件添加Ninject绑定,也可以吧这个方法用于对需要额外的构造器参数或者属性的控制器进行绑定,说的明白点就是我们上面展示的那些需要自己绑定的类。
创建了这个类可以用MVC框架对它进行注册,在Global.asax类的Application_Start方法中来完成注册,代码如下
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes); ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
}
现在我们使用NinjectControllerFactory来获得控制器的实例,而Ninject将自动第吧DI运用到控对象中。
希望这篇简单的介绍对你有用。
=============================================================
作者:Tyler Ning
出处:http://www.cnblogs.com/tylerdonet/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,如有问题,可以通过以下邮箱地址williamningdong@gmail.com 联系我,非常感谢。
Ninject简介(转)的更多相关文章
- IOC框架之Ninject 简介
还是那几句话: 学无止境,精益求精 十年河东,十年河西,莫欺少年穷 学历代表你的过去,能力代表你的现在,学习代表你的将来 上篇博客介绍了依赖注入的三种方式:构造方法注入,属性注入,接口注入!详情请参考 ...
- Ninject简介
1.为什么要用Ninject? Ninject是一个IOC容器用来解决程序中组件的耦合问题,它的目的在于做到最少配置.其他的的IOC工具过于依赖配置文件,需要使用assembly-qualified名 ...
- 依赖注入(DI)和Ninject,Ninject
我们所需要的是,在一个类内部,不通过创建对象的实例而能够获得某个实现了公开接口的对象的引用.这种“需要”,就称为DI(依赖注入,Dependency Injection),和所谓的IoC(控制反转,I ...
- Ninject依赖注入——构造函数的注入
1.Ninject简介 Ninject是基于.Net平台的依赖注入框架,它能够将应用程序分离成一个个高内聚.低耦合(loosely-coupled, highly-cohesive)的模块,然后以一种 ...
- Ninject依赖注入——构造函数、属性、方法和字段的注入
Ninject依赖注入——构造函数.属性.方法和字段的注入(三) 1.Ninject简介 Ninject是基于.Net平台的依赖注入框架,它能够将应用程序分离成一个个高内聚.低耦合(loosely-c ...
- 什么是IOC和什么是AOP,依赖注入(DI)和Ninject,Ninject
我们所需要的是,在一个类内部,不通过创建对象的实例而能够获得某个实现了公开接口的对象的引用.这种“需要”,就称为DI(依赖注入,Dependency Injection),和所谓的IoC(控制反转,I ...
- 记录.net 中的常见术语
--Entity Framework和NHibernate --EF和NH都是一种ORM技术.就是对象关系模型映射. --NHibernate和Entity Framework 4.0优劣势争论 -- ...
- 大话设计模式(C#)
还是那几句话: 学无止境,精益求精 十年河东,十年河西,莫欺少年穷 学历代表你的过去,能力代表你的现在,学习代表你的将来 问个问题: 如何写出高质量的代码?灵活,可扩展,易读,易维护,可重构,可复用. ...
- C# Note3:大话Ninject
前言 之所以研究Ninject,是因为初入职在开发XX项目的ComponentService部分时用到了它,一下子发现了它的强大.渐渐地发现在项目中,有时会用到优秀的第三方开源库,这些都是前人智慧的结 ...
随机推荐
- MySQL的用户密码过期功能详解
MySQL的用户密码过期功能详解 作者:chszs,未经博主允许不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs 先说明两个术语. Payment Ca ...
- rsyslog 读日志文件 ,当rsyslog 中断时,也会丢数据
rsyslog 日志服务器: [root@dr-mysql01 winfae_log]# grep scan0819 wj-proxy01-catalina.out.2016-08-19 [root@ ...
- 大型项目使用Automake/Autoconf完成编译配置
http://www.cnblogs.com/xf-linux-arm-java-android/p/3590770.htmlhttp://blog.csdn.net/zengraoli/articl ...
- GNU/Linux Distribution Timeline v12.10
GNU/Linux Distribution Timeline v12.10 原图下载 GNULinux Distribution Timeline 12.10.png GNU/Linux Distr ...
- #include <strstream>
std::ostrstream MYOUT(str, sizeof(str)); 拼接字符串 #include <iostream> #include <strstream> ...
- 支付宝“订单交易失败 ALI64” 报错的原因
移动快捷支付,往往需要集成支付宝的sdk,集成的过程相对简单,只要按照支付宝的文档,进行操作一般不会出问题. 下面主要说明一下,集成sdk后报 "订单交易失败 请稍后再试(ALI64)&qu ...
- C# System.Guid.NewGuid() 【转】
概念 GUID: 即Globally Unique Identifier(全球唯一标识符) 也称作 UUID(Universally Unique IDentifier) . GUID是一个通过特定算 ...
- OpenCV系列--摄像头控制的简单代码
操作系统:windows xp 开发工具:VS2008 opencv版本:2.1.0 依赖库:OpenCV2.1\lib\highgui.lib #include "cv.h" # ...
- Git 系列(五):三个 Git 图形化工具
在本文里,我们来了解几个能帮你在日常工作中舒服地用上 Git 的工具. 我是在这许多漂亮界面出来之前学习的 Git,而且我的日常工作经常是基于字符界面的,所以 Git 本身自带的大部分功能已经足够我用 ...
- Android 利用剪切板(clipboardManager )实现数据传递
首先是系统剪切板的调用服务: ClipboardManager ClipboardManager=getSystemService(Context.CLIPBOARD_SERVICE); 然后是写入, ...