1、Ninject依赖链注入:
public class ShoppingCart
{
private IValueCalc calc;
public ShoppingCart(IValueCalc ivc)
{
calc = ivc;
}
public decimal Total()
{
var prods = new[]
{
new Product{Name ="a",Price =15},
new Product{Name="b",Price =25},
new Product{Name ="c",Price =35}
};
return calc.ValueProducts(prods);
}
}
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 IValueCalc
{
decimal ValueProducts(params Product[] prods);
}
public class LinqValueCalc : IValueCalc
{
private IDiscount dis;
public LinqValueCalc(IDiscount dis)
{
this.dis = dis;
}
public System.Decimal ValueProducts(params Product[] prods)
{
return dis.DiscountTotal(prods.Sum(p => p.Price));
}
}
public interface IDiscount
{
decimal DiscountTotal(decimal total);
}
public class DiscountHelper:IDiscount
{
public decimal DiscountTotal(decimal total)
{
return total * 0.9m;
}
}
会发现ShoppingCart与LinqValueCalc解耦(借助于IValueCalc),LinqValueCalc与DiscountHelper解耦(借助于IDiscount),这样就形成了依赖链,还可以在DiscountHelper和其他类解耦(也是借助必要的接口),一直这样嵌套下去。
而是用Ninject只需注册bind就可以了 ,如:
static void Main(string[] args)
{
IKernel ninjectKernel = new StandardKernel();
ninjectKernel.Bind<IValueCalc>().To<LinqValueCalc>();
ninjectKernel.Bind<IDiscount>().To<DiscountHelper>();//将内嵌接口绑定到实现
IValueCalc cal = ninjectKernel.Get<IValueCalc>();//ninject在获取IValueCalc实现时,会自动发现内嵌的接口,并自动注入依赖,实现依赖链的注入
Console.WriteLine("Total:{0:C}", new ShoppingCart(cal).Total());
Console.ReadKey();
}
2、在依赖注入时,通过属性或构造函数的参数,动态传递值
在上面的例子中,折扣是9折:return total*0.9,如果想要动态(比如说不同商品的折扣从数据库中取)传递折扣值,那么可以这样改造DiscountHelper类:
public class DiscountHelper:IDiscount
{
public decimal disAmount { get; set; }
public decimal DiscountTotal(decimal total)
{
return total * (1-disAmount);
}
}
相应的ninject绑定代码就变成了:ninjectKernel.Bind<IDiscount>().To<DiscountHelper>().WithPropertyValue("disAmount",0.5m);//注意最后的方法调用
同样也可以使用构造函数:
public class DiscountHelper:IDiscount
{
public decimal disAmount { get; set; }
private decimal disParam;
public DiscountHelper(decimal disParam)
{
this.disParam = disParam;
}
public decimal DiscountTotal(decimal total)
{
return total * (1-disParam);
}
}
绑定语句:ninjectKernel.Bind<IDiscount>().To<DiscountHelper>().WithConstructorArgument("disParam", 0.4m);
3、自我绑定,由第一个特性可知,如果我们使用依赖的最外层类,那么会依次实现内层的自动依赖注入,那么ninject支持自我绑定,
可以将如下代码:
IValueCalc cal = ninjectKernel.Get<IValueCalc>();
ShoppingCart sc=new ShoppingCart(cal);
替换成更简洁的方式:ShoppingCart sc=ninjectKernel.Get<ShoppingCart>();
4、上述我们依赖注入是通过接口,也可以使用抽象类实现同样的功能,具体写法:ninject.Bind<抽象类>.To<实现类>();
5、条件依赖注入,即如果一个接口或抽象类有不同的实现,那么可以在解耦时,绑定不同的实现,具体语法:
ninject.Bind<接口或抽象类>.To<特定的实现类(多个中的一个)>.WhenInjectInto<依赖类(多个依赖类中的一个)>;
ninject是选择一个匹配度最好的调用。
关于ninject插件的用法,大家还有什么用的比较多,多多交流。