这次要介绍的是一个非常不错的DI(即依赖注入)框架,就是Ninject,通过使用此框架,可以非常方便地实现DI。不过在介绍此框架之前,先让我们再来看看到底为什么要使用依赖注入和其具体实现吧。 请大家先看以下代码,我们先创建最基本的产品类,然后添加一个价格计算接口和一个实现此接口的类:
//产品类 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 { set; get; } } //价格计算接口 public interface IValueCalculator { decimal ValueProducts(params Product[] products); } //实现价格计算接口 public class LinqValueCalculator : IValueCalculator { public decimal ValueProducts(params Product[] products) { return products.Sum(p => p.Price); } }
接下来再创建购物车类,然后将以上接口添加进去:
public class ShoppingCart { private IValueCalculator calculator;
public ShoppingCart(IValueCalculator calcParam) { calculator = calcParam; }
public decimal CalculateStockValue() { // 定义和设置产品信息 Product[] products = { new Product() { Name = "Kayak",Price = 275M}, new Product() { Name = "Lifejacket",Price = 48.95M}, new Product() { Name = "Soccer ball",Price = 19.50M}, new Product() { Name = "Stadium",Price = 79500M} }; // 计算总价格 decimal totalValue = calculator.ValueProducts(products);
// 返回计算结果 return totalValue; } }
从以上代码可看出,ShoppingCart和LinqValueCalculator都依赖于IValueCalculator接口,但ShoppingCart和LinqValueCalculator之间并没有直接关系,甚至ShoppingCart并不知道LinqValueCalculator的存在,这样的好处也显而易见,就是LinqValueCalculator可以随时更换而不会影响到ShoppingCart里的代码,因此也达到了松耦合的效果了。
以下是上面几个类的关系图:
OK,现在看看如何结合Ninject来使用以上代码。首先要为你的项目添加Ninject引用,在项目名称里点击右键,然后选择“Add PackageLibrary Reference”,然后只需在搜索框里输入 ninject ,这时就可看到下面的选择列表里出现了 Ninject的项目了,直接选择安装即可
为了方便演示,只需创建一个控制台项目即可。要使用Ninject,可直接调用IKernel接口,代码如下:
class Program { static void Main(string[] args) { IKernel ninjectKernel = new StandardKernel(); //绑定接口到实现类里 ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator<(); } }
以上代码将接口与实现类绑定起来了,然后再添加以下代码以实现ShoppingCart类:
// 获取实现的接口 IValueCalculator calcImpl = ninjectKernel.Get<IValueCalculator>(); // 创建实例注入到 ShoppingCart ShoppingCart cart = new ShoppingCart(calcImpl); // 执行计算功能以输出结果 Console.WriteLine("Total: {0:c}",cart.CalculateStockValue());
可能大家会感觉这样使用还不如直接调用来得方便啊,如果不使用 Ninject ,我们只需直接使用:
ShoppingCart cart = new ShoppingCart(new LinqValueCalculator());
这样就可以了,不是方便很多吗?为什么还要用Ninject写这么多代码呢? 嗯,以上其实只是一个最简单的为了演示的代码,如果随着复杂的多层接口的注入增加的话,就可以马上体现出Ninject的效率和好处了!
请继续看以下代码,我们再添加一个新的折扣接口:
//添加折扣接口 public interface IDiscountHelper { decimal ApplyDiscount(decimal totalParam); }
//实现不同的折扣 public class DefaultDiscountHelper : IDiscountHelper {
public decimal ApplyDiscount(decimal totalParam) { return (totalParam - (10m / 100m * totalParam)); } }
//为之前的价格功能里添加折扣功能,实现折扣接口 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)); } }
现在我们又多了一层注入的接口了,但使用Ninject的话就非常方便,只需添加多一行代码就可以了:
... IKernel ninjectKernel = new StandardKernel(); ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>(); //这是为新接口添加的,其他代码均不需改动 ninjectKernel.Bind<IDiscountHelper>().To<DefaultDiscountHelper>(); // 获取实现的接口 IValueCalculator calcImpl = ninjectKernel.Get<IValueCalculator>(); ShoppingCart cart = new ShoppingCart(calcImpl); Console.WriteLine("Total: {0:c}",cart.CalculateStockValue()); ...
随着代码接口的复杂性增多,就可以体现出Ninject的好处了
ASP.NET MVC中应用:
namespace NinjectDemo.Infrastructure { public class NinjectControllerFactory : DefaultControllerFactory { private IKernel ninjectKernel; public NinjectControllerFactory() { ninjectKernel = new StandardKernel(); AddBindings(); } protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { return controllerType == null ? null : (IController)ninjectKernel.Get(controllerType); } private void AddBindings() { // put additional bindings here ninjectKernel.Bind<IProductRepository>().To<FakeProductRepository>(); } } }
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory()); }
引用:http://www.coderblog.in/2011/09/using-ninject-for-di.html (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|