希望实现的效果是:对购物车中所有商品的总价,实现9折或8折:

当点击"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的更多相关文章

  1. MVC扩展控制器工厂,通过实现IControllerFactory,根据action名称生成不同的Controller

    关于控制器工厂的扩展,要么通过实现IControllerFactory接口,要么通过继承DefaultControllerFactory.本篇中,我想体验的是: 1.当请求经过路由,controlle ...

  2. MVC扩展控制器, 把部分视图转换成字符串(带验证信息), 并以json传递给前端视图

    当我们使用jQuery异步提交表单数据的时候,需要把部分视图转换成字符串(带验证信息),以json的形式传递给前端视图.   使用jQuery异步加载部分视图,返回内容追加到页面某个div:   jQ ...

  3. MVC项目实践,在三层架构下实现SportsStore-03,Ninject控制器工厂等

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  4. .NET/ASP.NET MVC Controller 控制器(IController控制器的创建过程)

    阅读目录: 1.开篇介绍 2.ASP.NETMVC IControllerFactory 控制器工厂接口 3.ASP.NETMVC DefaultControllerFactory 默认控制器工厂 4 ...

  5. .NET/ASP.NET MVC Controller 控制器(深入解析控制器运行原理)

    阅读目录: 1.开篇介绍 2.ASP.NETMVC Controller 控制器的入口(Controller的执行流程) 3.ASP.NETMVC Controller 控制器的入口(Controll ...

  6. 三、ASP.NET MVC Controller 控制器(二:IController控制器的创建过程)

    阅读目录: 1.开篇介绍 2.ASP.NETMVC IControllerFactory 控制器工厂接口 3.ASP.NETMVC DefaultControllerFactory 默认控制器工厂 4 ...

  7. 二、ASP.NET MVC Controller 控制器(一:深入解析控制器运行原理)

    阅读目录: 1.开篇介绍 2.ASP.NETMVC Controller 控制器的入口(Controller的执行流程) 3.ASP.NETMVC Controller 控制器的入口(Controll ...

  8. NET/ASP.NET MVC Controller 控制器(一:深入解析控制器运行原理)

    阅读目录: 1.开篇介绍 2.ASP.NETMVC Controller 控制器的入口(Controller的执行流程) 3.ASP.NETMVC Controller 控制器的入口(Controll ...

  9. ASP.NET MVC 创建控制器类过程

    MvcHandler.ProcessRequestInit()方法: 1.1获取控制器的名称string requiredString = this.RequestContext.RouteData. ...

随机推荐

  1. 为django的python manage.py加自定义命令

    计划在开发软件的过程中, 每次可以自己加入测试数据,这样就可以每次作全新的测试了. 将这个初始化django modules数据命令,将在manage.py里是最合适的. 下面我们就来实现吧. 参考文 ...

  2. pyspider 在ubuntu上安装失败怎么搞?

    pyspider 是一个非常不错的爬虫框架,在ubuntu上安装时报错误: 很明显pycurl的问题,pycurl没安装成功 pycurl 安装错误解决办法: sudo apt-get install ...

  3. day1作业:编写登陆接口

    作业一:编写登陆接口 1.输入用户名和密码 2.认证成功后显示欢迎信息 3.输错三次后锁定 思路:要求是编写登陆接口,那么要有一个存放用户信息的模块:三次后锁定,要有一个存放锁定用户信息的模块:我们知 ...

  4. MFC+WinPcap编写一个嗅探器之四(获取模块)

    这一节主要介绍如何获取设备列表,比较简单 获取设备列表主要是在CAdpDlg中完成,也就是对应之前创建的选择适配器模块,如图: 当打开选择适配器对话框后,在列表视图控件中显示当前主机所有适配器及适配器 ...

  5. 【LOJ】#2032. 「SDOI2016」游戏

    题解 看错题了,以为单次修改相当于一个覆盖,后来才明白"添加"-- 就相当于添加很多线段求最小值 首先这个等差数列添加的方式比较烦人,我们拆开两条链,一条s到lca,一条lca到t ...

  6. 【51nod】1934 受限制的排列

    题解 这题还要判无解真是难受-- 我们发现我们肯定能确定1的位置,1左右的两个区间是同理的可以确定出最小值的位置 我们把区间最小值看成给一个区间+1,构建出笛卡尔树,就求出了每一次取最小值和最小值左右 ...

  7. 【51nod】1822 序列求和 V5

    题解 我是zz吧 nonprime[i * prime[j]] = 0 = = 还以为是要卡常,卡了半天就是过不掉 我们来说这道题-- 首先,我们考虑一个\(K^2\)做法 \(f_{k}(N) = ...

  8. PCA(Principal Component Analysis)主成分分析

    PCA的数学原理(非常值得阅读)!!!!   PCA(Principal Component Analysis)是一种常用的数据分析方法.PCA通过线性变换将原始数据变换为一组各维度线性无关的表示,可 ...

  9. numpy.base_repr 方法解释

    首先看官方文档: numpy.base_repr(number, base=2, padding=0) 将给定的 number 值,换算成给定的 base 进制(默认 2 进制)的值,以字符串的形式返 ...

  10. 《Android源码设计模式》--策略模式

    No1: 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化. No2: 使用场景: 1)针对同一类型问题的多种处理方式,仅 ...