虽然我现在还不知道
IKernel ninjectKernel = new StandardKernel();
ninjectKernel.Bind<IValueCalculater>().To<LinqValueCalculator>();
IValueCalculater calcImpl = ninjectKernel.Get<IValueCalculater>();
换下面这一行的好处在哪,但我还是决定深入了解一下
IValueCalculater calcImpl = new LinqValueCalculator();
按照书中说的我做了一个平民版:如下:
Models中需要的类和接口:
//产品实体类
public class Product
{
public int ProductID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int Price { get; set; }
public string Category { get; set; }
}
//LINK表达式计算产品总价
public class LinqValueCalculator
{
public decimal ValueProducts(IEnumerable<Product> product)
{
return product.Sum(x => x.Price);
}
}
//购物车
public class ShoppingCart
{
//计算总价的工具类
private LinqValueCalculator cala;
//通过构造函数将计算总价的工具类传入
public ShoppingCart (LinqValueCalculator calcPram)
{
cala = calcPram;
}
//商品列表,在执行构造函数的时候可以通过属性初始化器赋值,也可稍后赋值
public IEnumerable<Product> Products { get; set; }
//使用工具类中的方法进行计算总价
public decimal CalculateProductTotal()
{
return cala.ValueProducts(Products);
}
}
控制器部分:
public class HomeController : Controller
{
// GET: Home
private Product[] products =
{
new Product {Name = "香蕉",Category = "水果",Price =2 ,ProductID=0},
new Product {Name = "外套",Category = "衣服",Price =200 ,ProductID=0},
new Product {Name = "平底锅",Category = "厨具",Price =50 ,ProductID=0},
new Product {Name = "枕头",Category = "家纺",Price =40 ,ProductID=0},
new Product {Name = "吹风机",Category = "小家具",Price =70 ,ProductID=0},
new Product {Name = "香皂",Category = "日用品",Price =8 ,ProductID=0}
};
/// <summary>
/// 本版本的 Index 方法 和 LinqValueCalculator 与 ShoppingCart 都是强耦合,
/// </summary>
/// <returns></returns>
public ActionResult Index()
{
LinqValueCalculator calc = new LinqValueCalculator();
ShoppingCart cart = new ShoppingCart(calc) { Products = products };
decimal totalValue = cart.CalculateProductTotal();
return View(totalValue);
}
}
解析:
可以看到ShoppingCart 和 LinqValueCalculator 是紧耦合的 而且
Home中的Index 对于 LinqValueCalculator 和 ShoppingCart的 耦合是相当高的,所以称之为平民版本
视图:
@model decimal
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
Total value is $@Model
</div>
</body>
</html>
运行结果:
如果后面业务的变动不在适合用 LinqValueCalculator 作为计算总价的方法,需要替换,即便保持替换方法中的总价函数名称和返回类型以及修饰符,还是和LinqValueCalculator 中一致也需要修改掉 两处地方 ,一处是ShoppingCart(购物车类)中的
一处是 HomeController 中的:
这感觉改起来是相当酸爽的,
是否进行强化 ? ==============>请添加强化石(DI容器)
战略两步走:
一、解开 ShoppingCart 与 LinqValueCalculator 的紧耦合关系:
思路:创建一个接口 呵呵哒 让 LinqValueCalculator 继承 , ShoppingCart 中的接收类型使用接口呵呵哒(好比 Object 可以接收 string 一样)
这个接口呵呵哒 类型实例可以接收 LinqValueCalculator ,由此ShoppingCart 与 LinqValueCalculator 的紧耦合关系解除;现在 Shopping与
接口呵呵哒 紧耦合,这是可以允许的,
情况就好像是 Shopping类是一个30岁的处男,现在的底线只要是雌性动物(只要继承了呵呵哒 就行),
它就不像17~18岁那会只要美女(LinqValueCalculator ).... 现在是来者不拒
实现代码:
/// <summary>
/// 计算总价的接口
/// </summary>
public interface IValueCAlculator
{
decimal ValueProducts(IEnumerable<Product> products);
}
//LINK表达式计算产品总价
public class LinqValueCalculator: IValueCAlculator
{
public decimal ValueProducts(IEnumerable<Product> product)
{
return product.Sum(x => x.Price);
}
}
//购物车
public class ShoppingCart
{
//计算总价的工具类
private IValueCAlculator cala;
//通过构造函数将计算总价的工具类传入
public ShoppingCart (IValueCAlculator calcPram)
{
cala = calcPram;
}
//商品列表,在执行构造函数的时候可以通过属性初始化器赋值,也可稍后赋值
public IEnumerable<Product> Products { get; set; }
//使用工具类中的方法进行计算总价
public decimal CalculateProductTotal()
{
return cala.ValueProducts(Products);
}
}
二、解开 Home与 LinqValueCalculator 的紧耦合关系,
现在Home中的情况: 情况似乎更糟了 ,又多了一个强耦合的IValueCAlculator 接口
怎么让Home 解开和 IValueCAlculator 与 IValueCAlculator 的实现类 LinqValueCalculator 的耦合呢?
Ninject的工作就是来处理这个问题的