依赖注入之Ninject框架

前端之家收集整理的这篇文章主要介绍了依赖注入之Ninject框架前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

这次要介绍的是一个非常不错的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

原文链接:https://www.f2er.com/javaschema/287032.html

猜你在找的设计模式相关文章