• Ninject学习笔记<三>


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

    1.介绍

    废话几句,Ninject是一种轻量级的、基础.NET的一个开源IoC框架,在对于MVC框架的学习中会用到IoC框架的,因为这种IoC开源框架有很多,本篇的主题只有一个,就是让阅读过本篇幅的朋友逗知道IoC框架在项目中的作用,以及它的重要性。 这样做的目的是以便在以后的学习工作中选择自己中意的一个IoC框架来学习、使用,或者是自己去实现一个。好了,不废话了。

    2.环境准备

    1.新建个4.0Framework的一个控制台应用程序项目,名称为IoCDemo

    2.在http://www.ninject.org/download网页中,下载Version 2.2版本的Ninject程序集(之前版本的不支持4.0库),下载完成解压后会看到如图1里的几个文件,在这里你只需要关心名称为Ninject的文件,其它的忽略掉。

    图1

     


    3.在项目中新建个Lib文件夹,并把Ninject.dll、Ninject.pdb和Ninject.xml三个文件拷贝到文件目录下,并且添加引用到项目中。如图2:

    图2

    环境准备工作做好了,可以安心的来看示例了。捎带一句Ninject.xml文件是程序集文件的注释,不过都是英文的,对于姿势水平不高的屌丝来说这并不算是福利,当然也包括本人。(ps:谷歌翻译什么的很好用)

    3.初步认识、了解

    从上一篇的文章中,可以了解到一个基础的IoC,这是站在容器对象的角度去考虑的,具体实现对象确实是可以动态的注入到容器对象中的。我们再看一下新的示例,并从中找到上一篇不足的地方,换个角度去看问题。

    我们先定义了一个商品类,内容只包含了商品的编号、名称和价格三个属性

    代码3-1

    复制代码
    1     /// <summary>
    2     /// 货品
    3     /// </summary>
    4     public class Commodity
    5     {
    6         public string CommodityID { get; set; }
    7         public string Name { get; set; }
    8         public float Price { get; set; }
    9     }
    复制代码

    商品类型定义好了之后,我们再定义个货品的计价规范和它的一个基础实现

    代码3-2

    复制代码
     1     /// <summary>
     2     /// 货品计价规范
     3     /// </summary>
     4     public interface IValuation
     5     {
     6         float CommodityValuation(params Commodity[] commodities);
     7     }
     8 
     9     /// <summary>
    10     /// 货品计价规范实现一:商品价格合计
    11     /// </summary>
    12     public class CommoditySumValuation : IValuation
    13     {
    14         public float CommodityValuation(params Commodity[] commodities)
    15         {
    16             return commodities.Sum(commodity => commodity.Price);
    17         }
    18     }
    复制代码

    这样看来架势和上一篇的相同,前段的确实是差不多的,不要着急慢慢来看。再定义个容器对象,并且通过构造注入的方式来实现解耦,让容器对象和具体实现彻底的分离了。

    代码3-3

    复制代码
     1     /// <summary>
     2     /// 购物车-容器对象
     3     /// </summary>
     4     public class ShoppingCart
     5     {
     6         private IValuation _Valuation;
     7         public ShoppingCart(IValuation valuation)
     8         {
     9             _Valuation = valuation;
    10         }
    11 
    12         public float CommodityTotalPrice()
    13         {
    14             Commodity[] commodities =
    15             {
    16                 new Commodity(){ CommodityID="A1", Price=14},
    17                 new Commodity(){ CommodityID="A2", Price=76.5f},
    18                 new Commodity(){ CommodityID="B2", Price=34.4f},
    19                 new Commodity(){ CommodityID="C4", Price=23.1f}
    20             };
    21 
    22             return _Valuation.CommodityValuation(commodities);
    23         }
    24     }
    复制代码

    对于上面那句话的定义,站在不同角度定义结果是不同的,如果站在容器对象的角度来看,确实是实现了解耦,如图3

    图3

    从图中可以明确的看到ShoppingCart类型(容器)和CommoditySumValuation类型(具体实现)没有任何的关系,从而以达到解耦的目的,但是问题要结合到实际从客户端调用容器对象来看:

    代码3-4

    复制代码
     1 namespace IoCDemo
     2 {
     3     class Program
     4     {
     5         static void Main(string[] args)
     6         {
     7             ShoppingCart shoppingCart = new ShoppingCart(new CommoditySumValuation());
     8 
     9         }
    10     }
    11 }
    复制代码

    代码看到这里,想必大家都会头疼了,这整的叫什么事,饶了一圈还是耦合了。如图4

    图4

    这种情况下IoC框架就可以派上用场了,本篇介绍的是Ninject,那当然是用Ninject了,根据前面的环境配置,

    代码3-5

    复制代码
     1 using Ninject;
     2 
     3 namespace IoCDemo
     4 {
     5     class Program
     6     {
     7         static void Main(string[] args)
     8         {
     9             #region IoC框架功能
    10             IKernel kernel = new StandardKernel();
    11             kernel.Bind<IValuation>().To<CommoditySumValuation>();
    12             IValuation valuation = kernel.Get<IValuation>();
    13             #endregion
    14 
    15             ShoppingCart shoppingCart = new ShoppingCart(valuation);
    16             Console.WriteLine(shoppingCart.CommodityTotalPrice().ToString());
    17             Console.ReadLine();
    18         }
    19     }
    20 }
    复制代码

    这里是通过Ninject中的IKernel类型的Bind泛型方法来绑定IValuation类型,用To泛型方法中的类型表示是Bind方法中类型的实现,这样在kernel.Get<IValuation>()的时候是返回的CommoditySumValuation类型。这里对Ninject的使用并不多做介绍,而是侧重的解释IoC的重要性及其作用。

    这个时候的依赖结构如下图5

    图5

    这样可能看不出IoC的效果,我们再新增一些需求,并且更改CommoditySumValuation实现类,

    代码3-6

    复制代码
     1     /// <summary>
     2     /// 计价折扣算法规范
     3     /// </summary>
     4     public interface IValuationDisCount
     5     {
     6         float ValuationDisCount(float listPrice);
     7     }
     8 
     9     /// <summary>
    10     /// 计价折扣算法规范实现一:九折 走起
    11     /// </summary>
    12     public class DisCount : IValuationDisCount
    13     {
    14 
    15         public float ValuationDisCount(float listPrice)
    16         {
    17             return listPrice - (listPrice * 10 / 100);
    18         }
    19     }
    复制代码

    添加了一个新需求规范和一个新的实现类,这样可以给商品总和来打折了,还需在CommoditySumValuation实现类中实现构造注入,修改代码如下:

    代码3-7

    复制代码
     1     /// <summary>
     2     /// 货品计价规范实现一:商品价格合计
     3     /// </summary>
     4     public class CommoditySumValuation : IValuation
     5     {
     6         private IValuationDisCount valuationDisCount;
     7 
     8         public CommoditySumValuation(IValuationDisCount valuationdiscount)
     9         {
    10             this.valuationDisCount = valuationdiscount;
    11         }
    12 
    13         public float CommodityValuation(params Commodity[] commodities)
    14         {
    15             return valuationDisCount.ValuationDisCount(commodities.Sum(commodity => commodity.Price));
    16         }
    17     }
    复制代码

    这个时候如果没有IoC框架的存在,看下客户端是怎么来调用的:

    代码3-8

    复制代码
     1 using Ninject;
     2 
     3 namespace IoCDemo
     4 {
     5     class Program
     6     {
     7         static void Main(string[] args)
     8         {
     9             ShoppingCart shoppingCart =
    10                 new ShoppingCart(new CommoditySumValuation(new DisCount()));
    11 
    12             Console.WriteLine(shoppingCart.CommodityTotalPrice().ToString());
    13             Console.ReadLine();
    14         }
    15     }
    16 }
    复制代码

    运行一下同样也能得到结果,但是不管怎么的去抽象,在客户端调用都需要直接依赖于实现类,而不是高层次的抽象,

    图7

    从图中可以看出来这是多么的恐怖。重新的修改下Main函数里的代码把IoC框架给使用起来。

    代码3-9

    复制代码
     1 using Ninject;
     2 
     3 namespace IoCDemo
     4 {
     5     class Program
     6     {
     7         static void Main(string[] args)
     8         {
     9             #region IoC框架功能
    10             IKernel kernel = new StandardKernel();
    11             kernel.Bind<IValuation>().To<CommoditySumValuation>();
    12             kernel.Bind<IValuationDisCount>().To<DisCount>();
    13             IValuation valuation = kernel.Get<IValuation>();
    14             #endregion
    15 
    16             ShoppingCart shoppingCart = new ShoppingCart(valuation);
    17 
    18             Console.WriteLine(shoppingCart.CommodityTotalPrice().ToString());
    19             Console.ReadLine();
    20         }
    21     }
    22 }
    复制代码

    结果如图8:

    图8

    再来看一下依赖结构,

    图9

    Ninject框架会检查要返回的类型所依赖的所有类型,并且也会动态的注入到类型当中。
    从图7和图9的对比中可以看出,只有通过增加IoC框架来进行客户端和具体实现的解耦,没有这个中间层的加入还真的不好来实现消除耦合,并且IoC框架还可以进行动态配置。
    本篇到这里结束了,对Ninject感兴趣的朋友请自行学习吧。

    作者:金源

    出处:http://www.cnblogs.com/jin-yuan/

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面

  • 相关阅读:
    深入protoBuf
    Golang数据库操纵对IN语句的支持
    golang几种常用配置文件使用方法总结(yaml、toml、json、xml、ini)
    golang实现rabbitmq消息队列失败尝试
    Trie性能分析之敏感词过滤golang
    Go语言cookie的基本操作
    微信二维码添加logo
    gin框架中间件
    gin入门-1
    2017-06-28(passwd 主要组与附属组 gpasswd newgrp groups)
  • 原文地址:https://www.cnblogs.com/abc8023/p/3875790.html
Copyright © 2020-2023  润新知