【转】Ninject的使用

转自: http://www.cnblogs.com/willick/p/3223042.html(整个系列的文章都不错,知识点全面,值得新手学习)

为什么需要依赖注入

在[ASP.NET MVC 小牛之路]系列的理解MVC模式文章中,我们提到MVC的一个重要特征是关注点分离(separation of concerns)。我们希望应用程序的各部分组件尽可能多的相互独立、尽可能少的相互依赖。

我们的理想情况是:一个组件可以不知道也可以不关心其他的组件,但通过提供的公开接口却可以实现其他组件的功能调用。这种情况就是所谓的松耦合

举个简单的例子。我们要为商品定制一个“高级”的价钱计算器LinqValueCalculator,这个计算器需要实现IValueCalculator接口。如下代码所示:

public interface IValueCalculator
{
    decimal ValueProducts(params Product[] products);
}

public class LinqValueCalculator : IValueCalculator
{
    public decimal ValueProducts(params Product[] products) {
        return products.Sum(p => p.Price);
    }
}

  Product类和前两篇博文中用到的是一样的。现在有个购物车ShoppingCart类,它需要有一个能计算购物车内商品总价钱的功能。但购物车本身没有计算的功能,因此,购物车要嵌入一个计算器组件,这个计算器组件可以是LinqValueCalculator组件,但不一定是LinqValueCalculator组件(以后购物车升级,可能会嵌入别的更高级的计算器)。那么我们可以这样定义购物车ShoppingCart类:

public class ShoppingCart {
    //计算购物车内商品总价钱
     public decimal CalculateStockValue() {
         Product[] products = {
             new Product {Name = "西瓜", Category = "水果", Price = 2.3M},
             new Product {Name = "苹果", Category = "水果", Price = 4.9M},
             new Product {Name = "空心菜", Category = "蔬菜", Price = 2.2M},
             new Product {Name = "地瓜", Category = "蔬菜", Price = 1.9M}
          };
        IValueCalculator calculator = new LinqValueCalculator();

         //计算商品总价钱
         decimal totalValue = calculator.ValueProducts(products);

         return totalValue;
     }
 }

  ShoppingCart类是通过IValueCalculator接口(而不是通过LinqValueCalculator)来计算商品总价钱的。如果以后购物车升级需要使用更高级的计算器,那么只需要改变第10行代码中new后面的对象(即把LinqValueCalculator换掉),其他的代码都不用变动。这样就实现了一定的松耦合。这时三者的关系如下图所示:

这个图说明,ShoppingCart类既依赖IValueCalculator接口又依赖LinqValueCalculator类。这样就有个问题,用现实世界的话来讲就是,如果嵌入在购物车内的计算器组件坏了,会导致整个购物车不能正常工作,岂不是要把整个购物车要换掉!最好的办法是将计算器组件和购物车完全独立开来,这样不管哪个组件坏了,只要换对应的组件即可。即我们要解决的问题是,要让ShoppingCart组件和LinqValueCalculator组件完全断开关系,而依赖注入这种设计模式就是为了解决这种问题。

什么是依赖注入

上面实现的部分松耦合显然并不是我们所需要的。我们所需要的是,在一个类内部,不通过创建对象的实例而能够获得某个实现了公开接口的对象的引用。这种“需要”,就称为DI(依赖注入,Dependency Injection),和所谓的IoC(控制反转,Inversion of Control )是一个意思。

DI是一种通过接口实现松耦合的设计模式。初学者可能会好奇网上为什么有那么多技术文章对DI这个东西大兴其笔,是因为DI对于基于几乎所有框架下,要高效开发应用程序,它都是开发者必须要有的一个重要的理念,包括MVC开发。它是解耦的一个重要手段。

DI模式可分为两个部分。一是移除对组件(上面示例中的LinqValueCalculator)的依赖,二是通过类的构造函数(或类的Setter访问器)来传递实现了公开接口的组件的引用。如下面代码所示:

public class ShoppingCart {
    IValueCalculator calculator;

    //构造函数,参数为实现了IValueCalculator接口的类的实例
    public ShoppingCart(IValueCalculator calcParam) {
        calculator = calcParam;
    }

    //计算购物车内商品总价钱
    public decimal CalculateStockValue() {
        Product[] products = {
            new Product {Name = "西瓜", Category = "水果", Price = 2.3M},
            new Product {Name = "苹果", Category = "水果", Price = 4.9M},
            new Product {Name = "空心菜", Category = "蔬菜", Price = 2.2M},
            new Product {Name = "地瓜", Category = "蔬菜", Price = 1.9M}
        };

        //计算商品总价钱
        decimal totalValue = calculator.ValueProducts(products);

        return totalValue;
    }
}

这样我们就彻底断开了ShoppingCart和LinqValueCalculator之间的依赖关系。某个实现了IValueCalculator接口的类(示例中的LinqValueCalculator)的实例引用作为参数,传递给ShoppingCart类的构造函数。但是ShoppingCart类不知道也不关心这个实现了IValueCalculator接口的类是什么,更没有责任去操作这个类。 这时我们可以用下图来描述ShoppingCart、LinqValueCalculator和IValueCalculator之间的关系:

在程序运行的时候,依赖被注入到ShoppingCart,这个依赖就是,通过ShoppingCart构造函数传递实现了IValueCalculator接口的类的实例引用。在程序运行之前(或编译时),ShoppingCart和任何实现IValueCalculator接口的类没有任何依赖关系。(注意,程序运行时是有具体依赖关系的。)

注意,上面示例使用的注入方式称为“构造注入”,我们也可以通过属性来实现注入,这种注入被称为“setter 注入”,就不举例了,朋友们可以看看T2噬菌体的文章依赖注入那些事儿来对DI进行更多的了解。

由于经常会在编程时使用到DI,所以出现了一些DI的辅助工具(或叫DI容器),如Unity和Ninject等。由于Ninject的轻量和使用简单,加上本人只用过Ninject,所以本系列文章选择用它来开发MVC应用程序。下面开始介绍Ninject,但在这之前,先来介绍一个安装Ninject需要用到的插件-NuGet。

使用NuGet安装库

NuGet 是一种 Visual Studio 扩展,它能够简化在 Visual Studio 项目中添加、更新和删除库(部署为程序包)的操作。比如你要在项目中使用Log4Net这个库,如果没有NuGet这个扩展,你可能要先到网上搜索Log4Net,再将程序包的内容解压缩到解决方案中的特定位置,然后在各项目工程中依次添加程序集引用,最后还要使用正确的设置更新 web.config。而NuGet可以简化这一切操作。例如我们在讲依赖注入的项目中,若要使用一个NuGet库,可直接右击项目(或引用),选择“管理NuGet程序包”(VS2010下为“Add Library Package Reference”),如下图:

在本文中我们只需要知道如何使用NuGet来安装库就可以了。NuGet的详细使用方法可查看MSDN文档:使用 NuGet 管理项目库

使用Ninject的一般步骤

在使用Ninject前先要创建一个Ninject内核对象,代码如下:

class Program {
    static void Main(string[] args) {
        //创建Ninject内核实例
        IKernel ninjectKernel = new StandardKernel();
    }
}

  使用Ninject内核对象一般可分为两个步骤。第一步是把一个接口(IValueCalculator)绑定到一个实现该接口的类(LinqValueCalculator),如下:

...
//绑定接口到实现了该接口的类
ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator<();
...

  

这个绑定操作就是告诉Ninject,当接收到一个请求IValueCalculator接口的实现时,就返回一个LinqValueCalculator类的实例。

第二步是用Ninject的Get方法去获取IValueCalculator接口的实现。这一步,Ninject将自动为我们创建LinqValueCalculator类的实例,并返回该实例的引用。然后我们可以把这个引用通过构造函数注入到ShoppingCart类。如下代码所示:

...
// 获得实现接口的对象实例
IValueCalculator calcImpl = ninjectKernel.Get<IValueCalculator>();
// 创建ShoppingCart实例并注入依赖
ShoppingCart cart = new ShoppingCart(calcImpl);
// 计算商品总价钱并输出结果
Console.WriteLine("Total: {0:c}", cart.CalculateStockValue());
...

  Ninject的使用的一般步骤就是这样。该示例可正确输出如下结果:

但看上去Ninject的使用好像使得编码变得更加烦琐,朋友们会问,直接使用下面的代码不是更简单吗:

...
IValueCalculator calcImpl = new LinqValueCalculator();
ShoppingCart cart = new ShoppingCart(calcImpl);
Console.WriteLine("Total: {0:c}", cart.CalculateStockValue());
...

  

的确,对于单个简单的DI,用Ninject确实显得麻烦。但如果添加多个复杂点的依赖关系,使用Ninject则可大大提高编码的工作效率。

Ninject如何提高编码效率

当我们请求Ninject创建某个类型的实例时,它会检查这个类型和其它类型之间的耦合关系。如果存在依赖关系,那么Ninject会根据依赖处理理它们,并创建所有所需类的实例。为了解释这句话和说明使用Ninject编码的便捷,我们再创建一个接口IDiscountHelper和一个实现该接口的类DefaultDiscountHelper,代码如下:

//折扣计算接口
public interface IDiscountHelper {
    decimal ApplyDiscount(decimal totalParam);
}

//默认折扣计算器
public class DefaultDiscountHelper : IDiscountHelper {
    public decimal ApplyDiscount(decimal totalParam) {
        return (totalParam - (1m / 10m * totalParam));
    }
}

  IDiscounHelper接口声明了ApplyDiscount方法,DefaultDiscounterHelper实现了该接口,并定义了打9折的ApplyDiscount方法。然后我们可以把IDiscounHelper接口作为依赖添加到LinqValueCalculator类中。代码如下:

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));
    }
}

  

LinqValueCalculator类添加了一个用于接收IDiscountHelper接口的实现的构造函数,然后在ValueProducts方法中调用该接口的ApplyDiscount方法对计算出的商品总价钱进行打折处理,并返回折后总价。

到这,我们先来画个图理一理ShoppingCart、LinqValueCalculator、IValueCalculator以及新添加的IDiscountHelper和DefaultDiscounterHelper之间的关系:

以此,我们还可以添加更多的接口和实现接口的类,接口和类越来越多时,它们的关系图看上去会像一个依赖“链”,和生物学中的分子结构图差不多。

按照前面说的使用Ninject的“二个步骤”,现在我们在Main中的方法中编写用于计算购物车中商品折后总价钱的代码,如下所示:

class Program {
      static void Main(string[] args) {
          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());
         Console.ReadKey();
     }
 }

  

代码一目了然,虽然新添加了一个接口和一个类,但Main方法中只增加了第6行一句代码,获取实现IValueCalculator接口的对象实例的代码不需要做任何改变。
定位到代码的第8行,这一行代码,Ninject为我们做的事是:
  当我们需要使用IValueCalculator接口的实现时(通过Get方法),它便为我们创建LinqValueCalculator类的实例。而当创建LinqValueCalculator类的实例时,它检查到这个类依赖IDiscountHelper接口。于是它又创建一个实现了该接口的DefaultDiscounterHelper类的实例,并通过构造函数把该实例注入到LinqValueCalculator类。然后返回LinqValueCalculator类的一个实例,并赋值给IValueCalculator接口的对象(第8行的calcImpl)。

总之,不管依赖“链”有多长有多复杂,Ninject都会按照上面这种方式检查依赖“链”上的每个接口和实现接口的类,并自动创建所需要的类的实例。在依赖“链”越长越复杂的时候,更能显示使用Ninject编码的高效率。

Ninject的绑定方式

我个人将Ninject的绑定方式分为:一般绑定、指定值绑定、自我绑定、派生类绑定和条件绑定。这样分类有点牵强,只是为了本文的写作需要和方便读者阅读而分,并不是官方的分类

1、一般绑定

在前文的示例中用Bind和To方法把一个接口绑定到实现该接口的类,这属于一般的绑定。通过前文的示例相信大家已经掌握了,在这就不再累述。

2、指定值绑定

我们知道,通过Get方法,Ninject会自动帮我们创建我们所需要的类的实例。但有的类在创建实例时需要给它的属性赋值,如下面我们改造了一下的DefaultDiscountHelper类:

public class DefaultDiscountHelper : IDiscountHelper {
    public decimal DiscountSize { get; set; } 

    public decimal ApplyDiscount(decimal totalParam) {
        return (totalParam - (DiscountSize / 10m * totalParam));
    }
}

  给DefaultDiscountHelper类添加了一个DiscountSize属性,实例化时需要指定折扣值(DiscountSize属性值),不然ApplyDiscount方法就没意义。而实例化的动作是Ninject自动完成的,怎么告诉Ninject在实例化类的时候给某属性赋一个指定的值呢?这时就需要用到参数绑定,我们在绑定的时候可以通过给WithPropertyValue方法传参的方式指定DiscountSize属性的值,如下代码所示:

public static void Main() {
    IKernel ninjectKernel = new StandardKernel();

    ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
    ninjectKernel.Bind<IDiscountHelper>()
        .To<DefaultDiscountHelper>().WithPropertyValue("DiscountSize", 5M);

    IValueCalculator calcImpl = ninjectKernel.Get<IValueCalculator>();
    ShoppingCart cart = new ShoppingCart(calcImpl);
    Console.WriteLine("Total: {0:c}", cart.CalculateStockValue());
    Console.ReadKey();
}

  

如果要给多个属性赋值,则可以在Bind和To方式后添加多个WithPropertyValue(<属性名>,<属性值>)方法。

我们还可以在类的实例化的时候为类的构造函数传递参数。为了演示,我们再把DefaultDiscountHelper类改一下:

public class DefaultDiscountHelper : IDiscountHelper {
    private decimal discountRate; 

    public DefaultDiscountHelper(decimal discountParam) {
        discountRate = discountParam;
    } 

    public decimal ApplyDiscount(decimal totalParam) {
        return (totalParam - (discountRate/ 10m * totalParam));
    }
}

  显然,DefaultDiscountHelper类在实例化的时候必须给构造函数传递一个参数,不然程序会出错。和给属性赋值类似,只是用的方法是WithConstructorArgument(<参数名>,<参数值>),绑定方式如下代码所示:

...
ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
ninjectKernel.Bind<IDiscountHelper>()
    .To< DefaultDiscountHelper>().WithConstructorArgument("discountParam", 5M);
...

  

同样,只需要更改一行代码,其他代码原来怎么写还是怎么写。如果构造函数有多个参数,则需在Bind和To方法后面加上多个WithConstructorArgument即可。

3.自我绑定

Niject的一个非常好用的特性就是自绑定。当通过Bind和To方法绑定好接口和类后,可以直接通过ninjectKernel.Get<类名>()来获得一个类的实例。

在前面的几个示例中,我们都是像下面这样来创建ShoppingCart类实例的:

...
IValueCalculator calcImpl = ninjectKernel.Get<IValueCalculator>();
ShoppingCart cart = new ShoppingCart(calcImpl);
...

  其实有一种更简单的定法,如下:

...
ShoppingCart cart = ninjectKernel.Get<ShoppingCart>();
...

  

这种写法不需要关心ShoppingCart类依赖哪个接口,也不需要手动去获取该接口的实现(calcImpl)。当通过这句代码请求一个ShoppingCart类的实例的时候,Ninject会自动判断依赖关系,并为我们创建所需接口对应的实现。这种方式看起来有点怪,其实中规中矩的写法是:

...
ninjectKernel.Bind<ShoppingCart>().ToSelf();
ShoppingCart cart = ninjectKernel.Get<ShoppingCart>();
...

这里有自我绑定用的是ToSelf方法,在本示例中可以省略该句。但用ToSelf方法自我绑定的好处是可以在其后面用WithXXX方法指定构造函数参数、属性等等的值。

4.派生类绑定

通过一般绑定,当请求一个接口的实现时,Ninject会帮我们自动创建实现接口的类的实例。我们说某某类实现某某接口,也可以说某某类继承某某接口。如果我们把接口当作一个父类,是不是也可以把父类绑定到一个继承自该父类的子类呢?我们来实验一把。先改造一下ShoppingCart类,给它的CalculateStockValue方法改成虚方法:

public class ShoppingCart {
    protected IValueCalculator calculator;
    protected Product[] products;

    //构造函数,参数为实现了IEmailSender接口的类的实例
    public ShoppingCart(IValueCalculator calcParam) {
        calculator = calcParam;
        products = new[]{
            new Product {Name = "西瓜", Category = "水果", Price = 2.3M},
            new Product {Name = "苹果", Category = "水果", Price = 4.9M},
            new Product {Name = "空心菜", Category = "蔬菜", Price = 2.2M},
            new Product {Name = "地瓜", Category = "蔬菜", Price = 1.9M}
        };
    }

    //计算购物车内商品总价钱
    public virtual decimal CalculateStockValue() {
        //计算商品总价钱
        decimal totalValue = calculator.ValueProducts(products);
        return totalValue;
    }
}

再添加一个ShoppingCart类的子类:

public class LimitShoppingCart : ShoppingCart {
    public LimitShoppingCart(IValueCalculator calcParam)
        : base(calcParam) {
    }

    public override decimal CalculateStockValue() {
        //过滤价格超过了上限的商品
        var filteredProducts = products.Where(e => e.Price < ItemLimit);
        return calculator.ValueProducts(filteredProducts.ToArray());
    }

    public decimal ItemLimit { get; set; }
} 

然后把父类ShoppingCart绑定到子类LimitShoppingCart:

public static void Main() {
    IKernel ninjectKernel = new StandardKernel();

    ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
    ninjectKernel.Bind<IDiscountHelper>().To<DefaultDiscountHelper>()
        .WithPropertyValue("DiscountSize", 5M);
    //派生类绑定
    ninjectKernel.Bind<ShoppingCart>().To<LimitShoppingCart>()
        .WithPropertyValue("ItemLimit", 3M);

    ShoppingCart cart = ninjectKernel.Get<ShoppingCart>();
    Console.WriteLine("Total: {0:c}", cart.CalculateStockValue());
    Console.ReadKey();
}

  

从运行结果可以看出,cart对象调用的是子类的CalculateStockValue方法,证明了可以把父类绑定到一个继承自该父类的子类。通过派生类绑定,当我们请求父类的时候,Ninject自动帮我们创建一个对应的子类的实例,并将其返回。由于抽象类不能被实例化,所以派生类绑定在使用抽象类的时候非常有用。

5.条件绑定

当一个接口有多个实现或一个类有多个子类的时候,我们可以通过条件绑定来指定使用哪一个实现或子类。为了演示,我们给IValueCalculator接口再添加一个实现,如下:

public class IterativeValueCalculator : IValueCalculator { 

    public decimal ValueProducts(params Product[] products) {
        decimal totalValue = 0;
        foreach (Product p in products) {
            totalValue += p.Price;
        }
        return totalValue;
    }
}

IValueCalculator接口现在有两个实现:IterativeValueCalculator和LinqValueCalculator。我们可以指定,如果是把该接口的实现注入到LimitShoppingCart类,那么就用IterativeValueCalculator,其他情况都用LinqValueCalculator。如下所示:

public static void Main() {
    IKernel ninjectKernel = new StandardKernel();

    ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
    ninjectKernel.Bind<IDiscountHelper>().To<DefaultDiscountHelper>()
        .WithPropertyValue("DiscountSize", 5M);
    //派生类绑定
    ninjectKernel.Bind<ShoppingCart>().To<LimitShoppingCart>()
        .WithPropertyValue("ItemLimit", 3M);
    //条件绑定
    ninjectKernel.Bind<IValueCalculator>()
        .To<IterativeValueCalculator>().WhenInjectedInto<LimitShoppingCart>();

    ShoppingCart cart = ninjectKernel.Get<ShoppingCart>();
    Console.WriteLine("Total: {0:c}", cart.CalculateStockValue());
    Console.ReadKey();
}

运行结果:

运行结果是6.4,说明没有打折,即调用的是计算方法是IterativeValueCalculator的ValueProducts方法。可见,Ninject会查找最匹配的绑定,如果没有找到条件绑定,则使用默认绑定。在条件绑定中,除了WhenInjectedInto方法,还有When和WhenClassHas等方法,朋友们可以在使用的时候再慢慢研究。

在ASP.NET MVC中使用Ninject

本文用控制台应用程序演示了Ninject的使用,但要把Ninject集成到ASP.NET MVC中还是有点复杂的。首先要做的事就是创建一个继承System.Web.Mvc.DefaultControllerFactory的类,MVC默认使用这个类来创建Controller类的实例(后续博文会专门讲这个)。代码如下:

using System;
using Ninject;
using System.Web.Mvc;
using System.Web.Routing;

namespace MvcApplication1 {
    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() {
            // 在这添加绑定,
            // 如:ninjectKernel.Bind<IProductRepository>().To<FakeProductRepository>();
        }
    }
}

现在暂时不解释这段代码,大家都看懂就看,看不懂就过,只要知道在ASP.NET MVC中使用Ninject要做这么一件事就行。

添加完这个类后,还要做一件事,就是在MVC框架中注册这个类。一般我们在Global.asax文件中的Application_Start方法中进行注册,如下所示:

protected void Application_Start() {
    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);

    ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
}

注册后,MVC框架就会用NinjectControllerFactory类去获取Cotroller类的实例。在后续博文中会具体演示如何在ASP.NET MVC中使用Ninject,这里就不具体演示了,大家知道需要做这么两件事就行。

虽然我们前面花了很大功夫来学习Ninject就是为了在MVC中使用这样一个NinjectControllerFactory类,但是了解Ninject如何工作是非常有必要的。理解好了一种DI容器,可以使得开发和测试更简单、更高效。

时间: 2024-07-30 21:09:53

【转】Ninject的使用的相关文章

Ninject之旅之五:Ninject XML配置

摘要 使用XML配置,需要添加Ninject XML扩展的引用.下一步是添加一个或多个包含类型注册的XML文件.记得这些文件应该跟应用程序一起发布.因此不要忘记将XML文件的属性设置成“Copy if newer”. XML配置文件像下面的配置一样: <module name="moduleName"> <bind service="Namespace.IService1, AssemblyName" to="Namespace.Conc

Ninject之旅之八:Ninject插件模型

摘要 在前面的章节中,我们看了在单一的绑定条件下Ninject能够处理依赖类型,就是说,每个服务类型只绑定到单一的实现类型.然而,有些情况下我们需要绑定一个抽象服务类型到多个实现,这叫多个绑定.多个绑定有两种情况.第一个是插件模型实现,另一个是上下文绑定.这篇文章介绍插件模型实现,下一篇文章介绍上下文绑定. 插件模型让一个应用程序获得很强的可扩展性而不用修改源代码.下面的例子,我们将实现一个音乐播放器应用程序,使用解码插件来支持不同的音乐格式.这个应用程序使用两个内置的解码器,也可以添加更多的解

未能加载文件或程序集 Ninject.Web.Common, Version=3.2.0.0

在Web MVC4中使用NuGet添加NInject.MVC4后,编译报了个警告: 发现同一依赖程序集的不同版本之间存在冲突 然后在运行时就运行到var kernel = new StandardKernel()就报异常: 程序集清单定义与程序集引用不匹配 无法运行,经检查运行时程序清单是Ninject.Web.Common3.2,但项目安装的却是Ninject.Web.Common3.0. 解决方法:用NuGet先安装Ninject.Web.Common,再安装NInject.MVC4,即解决

使用Ninject+Moq在单元测试中抽象数据访问层

一.测试方法的业务逻辑时,通常都需要从数据库读取测试数据,但是每次初始化数据库数据都很麻烦,也会影响到其它业务对数据的访问,怎样抽象数据访问层呢?就是用Moq去模拟数据访问的逻辑 二.步骤如下 2.1 定义数据访问接口和实现 public interface IDBAccess { List<string> GetList(string request); } public class DBAccessImp : IDBAccess { public List<string> Ge

ASP.NET MVC学前篇之Ninject的初步了解

1.介绍 废话几句,Ninject是一种轻量级的.基础.NET的一个开源IoC框架,在对于MVC框架的学习中会用到IoC框架的,因为这种IoC开源框架有很多,本篇的主题只有一个,就是让阅读过本篇幅的朋友逗知道IoC框架在项目中的作用,以及它的重要性. 这样做的目的是以便在以后的学习工作中选择自己中意的一个IoC框架来学习.使用,或者是自己去实现一个.好了,不废话了. 2.环境准备 1.新建个4.0Framework的一个控制台应用程序项目,名称为IoCDemo 2.在http://www.nin

Ninject之旅之十三:Ninject在ASP.NET MVC程序上的应用

摘要: 在Windows客户端程序(WPF和Windows Forms)中使用Ninject和在控制台应用程序中使用Ninject没什么不同.在这些应用程序里我们不需要某些配置用来安装Ninject,因为在Windows客户端应用程序里,开发者可以控制UI组件的实例化(Forms或Windows),可以很容易地委托这种控制到Ninject.然而在Web应用程序里,就不同了,因为框架负责了实例化UI元素.因此,我们需要知道怎样告诉框架委托这种控制责任给Ninject.幸运的是,让ASP.NET M

Ninject之旅之十一:Ninject动态工厂(附程序下载)

摘要 如果我们已经知道了一个类所有的依赖项,在我们只需要依赖项的一个实例的场景中,在类的构造函数中引入一系列的依赖项是容易的.但是有些情况,我们需要在一个类里创建依赖项的多个实例,这时候Ninject注入就不够用了.也有些情况,我们不知道一个消费者可能需要哪个服务,因为他可能在不同的场合下需要不同的服务,而且在创建类的时候实例化所有依赖项也不合理.这样的情况,动态工厂可以帮忙.我们可以设计我们的类让他依赖一个工厂,而不是依赖这个工厂能够创建的对象.然后,我们能够命令工厂去通过命令创建需要的类型和

Ninject之旅之七:Ninject依赖注入

摘要 可以使用不同的模式向消费者类注入依赖项,向构造器里注入依赖项是期中一种.有一些遵循的模式用来注册依赖项,同时有一些需要避免的模式,因为他们经常导致不合乎需要的结果.这篇文章讲述那些跟Ninject功能相关的模式和反模式.然而,全面的介绍可以在Mark Seemann的书<Dependency Injection in .NET>中找到. 1.构造函数注入 构造函数时推荐的最常用的向一个类注册依赖项的模式.一般来说,这种模式应该经常被用作主要的注册模式,除非我们不得不使用其他的模式.在这个

使用Ninject进行DI(依赖注入)

Ninject是一个快如闪电.超轻量级的基于.Net平台的依赖注入框架.它能够帮助你把应用程序分离成一个个松耦合.高内聚的模块,然后用一种灵活的方式组装起来.通过使用Ninject配套你的软件架构,那么代码将会变得更加容易编写.重用性强.易于测试和修改.下面是一个简单的调用示例: 定义接口与基础类 interface IDocumentDAL { string Save(Document Entity); } public class Document { public int Id { get

使用 Ninject

在[ASP.NET MVC 小牛之路]系列上一篇文章(依赖注入(DI)和Ninject)的末尾提到了在ASP.NET MVC中使用Ninject要做的两件事情,续这篇文章之后,本文将用一个实际的示例来演示Ninject在ASP.NET MVC中的应用. 为了更好的理解和撑握本文内容,强烈建议初学者阅读本文前先阅读依赖注入(DI)和Ninject. 本文目录: 准备工作 新建一个名为BookShop的空白解决方案.在该解决方案中分别添加一个名为BookShop.WebUI的MVC空应用程序,和一个