MVC扩展控制器工厂,通过继承DefaultControllerFactory来决定使用哪个接口实现,使用Ninject
希望实现的效果是:对购物车中所有商品的总价,实现9折或8折:
□ 思路
8折或9折是打折接口的不同实现,关键是:由什么条件决定使用哪种打折方式?
--当点击8折或9折链接的时候,把参数放在路由中,然后在自定义控制器工厂中根据参数的不同选择使用哪种打折方式。
□ model
public class CartLine
{
public int Id { get; set;
}
public string Name { get; set;
}
public decimal Price { get; set;
}
public int Quantity { get; set;
}
}
□ 接口
using MvcApplication2.Models;
namespace MvcApplication2
{
public interface
IDiscount
{
decimal GetFinalPrice(List<CartLine> cartLines);
}
}
□ 接口的2种实现
using System.Collections.Generic;namespace MvcApplication2.implementation{public class NineDiscount : IDiscount
{public decimal GetFinalPrice(List<Models.CartLine> cartLines)
{ decimal result = 0.0M;foreach (var item in cartLines)
{result += item.Price*item.Quantity;
}
return result*(90M/100M);}
}
}
using System.Collections.Generic;namespace MvcApplication2.implementation{public class EightDiscount : IDiscount
{public decimal GetFinalPrice(List<Models.CartLine> cartLines)
{ decimal result = 0.0M;foreach (var item in cartLines)
{result += item.Price * item.Quantity;
}
return result * (80M / 100M);}
}
}
□ HomeController
using System.Collections.Generic;using System.Web.Mvc;using MvcApplication2.Models;namespace MvcApplication2.Controllers{public class HomeController : Controller
{ public ActionResult Index() { List<CartLine> cartLines = new List<CartLine>() {new CartLine(){Id = 1, Name = "Product1", Price = 80M, Quantity = 2},
new CartLine(){Id = 2, Name = "Product2", Price = 100M, Quantity = 3},
};
Session["cart"] = cartLines; return View(cartLines);}
}
}
□ Home/Index.cshtml
把不同的打折方式放在路由中传递。
@model List<MvcApplication2.Models.CartLine>
@{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml";}
<h2>Index</h2>
<table>
<tr style="background-color: #e3e3e3;"><td>产品</td>
<td>价格</td>
<td>数量</td>
</tr>
@foreach (var item in Model)
{<tr>
<td>@item.Name</td>
<td>@string.Format("{0:C}", item.Price)</td>
<td>@item.Quantity</td>
</tr>
}
</table>
<p>
@Html.ActionLink("9折购买", "Index", "Shop", new {policy = "Nine"},new {})
</p>
<p>
@Html.ActionLink("8折购买", "Index", "Shop", new {policy = "Eight"},new {})
</p>
□ 自定义控制器工厂,使用Ninject,根据路由参数policy的不同,决定选择具体的打折接口实现
using System;using System.Web.Mvc;using System.Web.Routing;using MvcApplication2.implementation;using Ninject;namespace MvcApplication2.Extension{public class NinjectControllerFactory : DefaultControllerFactory
{IKernel ninjectKernel;
string policy = "";
public NinjectControllerFactory() { ninjectKernel = new StandardKernel();}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{if (requestContext.RouteData.Values["policy"] != null)
{ policy = requestContext.RouteData.Values["policy"].ToString();}
AddBindings();
return controllerType == null ? null : (IController) ninjectKernel.Get(controllerType);
}
private void AddBindings()
{ switch (policy) {case "Eight":
ninjectKernel.Rebind<IDiscount>().To<EightDiscount>();
break;case "Nine":
ninjectKernel.Rebind<IDiscount>().To<NineDiscount>();
break; default:ninjectKernel.Rebind<IDiscount>().To<NineDiscount>();
break;}
}
}
}
□ 自定义控制器工厂全局注册
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
□ ShopController中使用打折接口方法
using System;using System.Collections.Generic;using System.Web.Mvc;using MvcApplication2.Models;namespace MvcApplication2.Controllers{public class ShopController : Controller
{ public IDiscount _Discount; public ShopController(IDiscount discount) { this._Discount = discount;}
public ActionResult Index(string policy)
{ List<CartLine> cartLines = new List<CartLine>();if (Session["cart"] != null)
{ cartLines = (List<CartLine>)Session["cart"];}
ViewData["total"] = String.Format("{0:C}",_Discount.GetFinalPrice(cartLines));
return View();}
}
}
□ Shop/Index.cshtml
@{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml";}
打折后的价格为: @ViewData["total"]
□ 自定义路由
为了让url更直观,符合controller/action/paramter:
routes.MapRoute(
name: "Default", url: "{controller}/{action}/{policy}",defaults: new { controller = "Home", action = "Index", policy = UrlParameter.Optional }
);
MVC扩展控制器工厂,通过继承DefaultControllerFactory来决定使用哪个接口实现,使用Ninject,布布扣,bubuko.com


