Pro ASP.NET MVC 3 Framework学习笔记之九
接着上次的Ninject的笔记,如果你是初次路过,可以先看看我前面的笔记。
一,创建依赖链(Chains of Dependency)
当我们向Ninject请求创建一个类型时,Ninject会去检查该类型和其他类型之间的耦合关系。如果有额外的依赖,Ninject也会解析它们并创建我们需要的所有类的实例。为了进一步说明,我们创建一个新的接口和一个实现该接口的类。请注意我们的例子是跟前面的笔记衔接的,所以如果你打算跟着一起操作的话,最好能够去看看前面的笔记。
创建一个IDiscountHelper如下所示:
public inte易做图ce IDiscountHelper
{
//Product打折应用
decimal ApplyDiscount(decimal totalParam);
}
创建一个实现IDiscountHelper的类如下所示:
public class DefaultDiscountHelper : IDiscountHelper
{
public decimal ApplyDiscount(decimal totalParam)
{
return (totalParam - (10m / 100m * totalParam)); //打9折
}
}
下面在LinqValueCalculator.cs添加依赖(这个类是前面的笔记里面的)
public class LinqValueCalculator : IValueCalculator
{
private IDiscountHelper discounter;
public LinqValueCalculator(IDiscountHelper discountParam)
{
discounter = discountParam;
}
public decimal ValueProducts(params Product[] products)
{
return discounter.ApplyDiscount(products.Sum(p => p.Price));
}
}
同样是通过Constructor Injection的方式
下面采取同样的方式将接口绑定到实现,如下所示:
static void Main(string[] args)
{
IKernel ninjectKernel = new StandardKernel();
//绑定接口到其对应的实现
ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
ninjectKernel.Bind<IDiscountHelper>().To<DefaultDiscountHelper>();
//获取接口实现
IValueCalculator calcuImpl = ninjectKernel.Get<IValueCalculator>();
ShoppingCart cart = new ShoppingCart(calcuImpl);
//执行
Console.WriteLine("Tatol:{0:c}", cart.CalculateStockValue());
}
我们使用Ninject将两个接口分别绑定到对应的实现类,我们不必改变实现IValueCalculator类的任何代码。Ninject知道当我们请求IValueCalculator的类型时就实例化LinqValueCalculator对象返回给我们。它会去检查这个类,并发现LinqValueCalculator依赖另一个接口,并且这个接口是它能解析的,Ninject创建一个DefaultDiscountHelper的实例注入LinqValueCalculator类的构造器,并返回IValueCalculator类型的对象。Ninject会只用这种方式检查每一个要实例化的类的依赖,不管涉及的依赖链有多复杂,多冗长。
二,指定属性和参数值
1.我们可以提供一些属性的具体值或者详细信息给Ninject,当我们要绑定接口到实现的时候。上面的例子里面我的打折9折,而且是写死的。现在我们对其进行修改,如下所示:
public class DefaultDiscountHelper : IDiscountHelper
{
public decimal DiscountSize { get; set; }
public decimal ApplyDiscount(decimal totalParam)
{
return (totalParam - (DiscountSize / 100m * totalParam));
}
}
这里我们定义了一个属性来表示具体的折扣。当我们再来绑定这个具体的类时,我们可以进行下面的操作.如下所示:
static void Main(string[] args)
{
IKernel ninjectKernel = new StandardKernel();
//绑定接口到其对应的实现
ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
//ninjectKernel.Bind<IDiscountHelper>().To<DefaultDiscountHelper>();
ninjectKernel.Bind<IDiscountHelper>().To<DefaultDiscountHelper>().WithPropertyValue("DiscountSize", 50m);//打5折哈
//获取接口实现
IValueCalculator calcuImpl = ninjectKernel.Get<IValueCalculator>();
ShoppingCart cart = new ShoppingCart(calcuImpl);
//执行
Console.WriteLine("Tatol:{0:c}", cart.CalculateStockValue());
}
当然如果你有多个属性,可以接用"."链式的添加。
2.上面是通过定义一个属性来实现折扣,我们也可以通过定义在构造器里的参数实现,如下所示:
public class DefaultDiscountHelper : IDiscountHelper
{
private decimal discountRate;
public DefaultDiscountHelper(decimal discountParam)
{
discountRate = discountParam;
}
public decimal ApplyDiscount(decimal totalParam)
{
return (totalParam - (discountRate/ 100m * totalParam));
}
}
这个时候我们绑定的时候是这样的:ninjectKernel.Bind<IDiscountHelper>().To< DefaultDiscountHelper>().WithConstructorArgument("discountParam", 50M);
同样我们如果有多个构造器参数,也采用"."的方式链式添加。
3.使用Self-Binding
一个非常有用的功能:Self-Binding(自我绑定)能够完全将Ninject整合到我们的代码里面,也就是来自Ninject内核被请求的类的地方。这可能看起来有点奇怪,这也意味着我们不用手动的执行DI的初始化。向下面这个地方:
IValueCalculator calcImpl = ninjectKernel.Get<IValueCalculator>();
ShoppingCart cart = new ShoppingCart(calcImpl);
我们可以简单的请求一个ShoppingCart的实例并让Ninject挑选出对IValueCalculator依赖的类。通过这种方式:ShoppingCart cart = ninjectKernel.Get<ShoppingCart>
补充:Web开发 , ASP.Net ,