ASP.NET MVC学前篇之扩展方法、链式编程

前言

目的没有别的,就是介绍几点在ASP.NETMVC 用到C#语言特性,还有一些其他琐碎的知识点,强行的划分一个范围的话,只能说都跟MVC有关,有的是外围的知识,有的是包含在框架内的。 MVC学前篇字样?有噱头的成分也有真实的成分,所以工欲善其事,必先利其器。器是什么?基础嘛,虽然说MVC框架中涉及到的知识很多很多也不是我一篇两篇能说完的,我能做的就是知道多少就跟大家分享多少,当然了随着时间的推移会完善这个系列。

1扩展方法

扩展方法是C# 3.0特性里的知识,它用在最多的地方是在Linq中,把众多的查询功能添加到了IEnumerable和IEnumerable<T>类型中, 这里不说太多,不然就扯Linq了。

运用的实际场景:有个购物清单(购物车)对象,它包含有添加、删除清单内物品的功能

商品对象,它包含 商品名称、商品价格两个属性

代码1-1

 namespace BlogCase
public class Commodity
{
public string Name { get; set; }
public float Price { get; set; }
} namespace BlogCase
/// <summary>
/// 购物清单
/// </summary>
public class ShoppingList
{
private List<Commodity> _Commodities; public List<Commodity> Commodities
{
get { return _Commodities; }
} public ShoppingList()
{
_Commodities = new List<Commodity>();
} public bool AddCommodity(Commodity commodity)
{
_Commodities.Add(commodity);
return true;
} public bool RemoveCommodity(Commodity commodity)
{
if (_Commodities.Contains(commodity))
{
_Commodities.Remove(commodity);
return true;
}
else
{
return false;
}
}
}

然后在这个令人不安、惶恐、期待、兴奋的新需求来了,要求清单可以提供一个清单内部所有货品价格的合计而又不破坏对象结构.
对的。这是非常合理的需求,现在咒骂也于事无补,因为需求总是未知的。在焦急、无奈中曙光就降临了,它就是C# 3.0中的特性扩展方法。

来看代码1-2

代码1-2

 using BlogCase;
using System.Linq; namespace BlogCase.Extension
{
public static class ShoppingListExtension
{
public static float Total(this ShoppingList shoppintlist)
{
return shoppintlist.Commodities.Sum(commodity => commodity.Price);
}
}
}

这里要说的是ShoppingListExtension类型是一个静态类,里面定义了一个静态方法Total,方法的签名是ShoppingList类型的参数,唯一不同的是在ShoppingList类型前面多了个this关键字,这时对ShoppingList类型的扩展方法已经定义好了。来看下示例代码1-3的使用吧。

代码1-3

 using BlogCase.Extension;

 namespace BlogCase
{
class Program
{
static void Main(string[] args)
{
ShoppingList shoppinglistTest = new ShoppingList();
shoppinglistTest.AddCommodity(new Commodity() { Name = "A", Price = 14.3f });
shoppinglistTest.AddCommodity(new Commodity() { Name = "B", Price = });
shoppinglistTest.AddCommodity(new Commodity() { Name = "C", Price = 27.9f });
shoppinglistTest.AddCommodity(new Commodity() { Name = "D", Price = 34.3f });
Console.WriteLine(shoppinglistTest.Total().ToString());
Console.ReadLine();
}
}
}

这里需要注意的是需要引用扩展方法类ShoppingListExtension所在的命名空间,在VS开发环境中,扩展方法的图标也和普通方法的不一样。如图1

图1

运行一下代码1-3,结果如图2。

图2

2链式编程思想

上面的内容是对类型来做扩展,添加了个扩展方法,这样对象间的耦合还是比较大的,假使修改了ShoppingList的内部结构,那ShoppingListExtension那里也得做相对应的修改,这里就要提到为什么要面相抽象编程了,后续的篇幅会提到。
现在我们要做的就是把ShoppingListExtension中的依赖类型换位更高层次的类型,并且再添加个扩展方法,用于过滤一些数据。由此全部结合起来可以看到一个链式编程的模型,对于学习linq和一些其他知识,这都是一个好的铺垫。

看下代码2-1示例,这是修改后的ShoppingList类型。

代码2-1

 namespace BlogCase
{
public class ShoppingList : IEnumerable<Commodity>, IEnumerator<Commodity>
{
private List<Commodity> _Commodities = new List<Commodity>();
public void Add(Commodity commodity)
{
_Commodities.Add(commodity);
}
public IEnumerator<Commodity> GetEnumerator()
{
return this;
}
IEnumerator IEnumerable.GetEnumerator()
{
return this;
}
private int _index = -;
public Commodity Current
{
get
{
return _Commodities[_index];
}
}
public void Dispose()
{ }
object System.Collections.IEnumerator.Current
{
get
{
return Current;
}
}
public bool MoveNext()
{
if (_index < _Commodities.Count)
{
_index++;
}
return (!(_index == _Commodities.Count));
}
public void Reset()
{
_index = -;
}
}
}

重新定义了ShoppingList类型,让其实现IEnumerable<Commodity>接口类型和IEnumerator<Commodity>接口类型,为什么要实现IEnumerable<Commodity>接口类型呢?因为示例代码中也要用到Linq的扩展方法,那些扩展方法是基于IEnumerable<T>类型扩展的,在第一部分中已经使用到了,细心的朋友可能已经留意到了。

对ShoppingListExtension类型也稍作修改,添加了新的扩展方法,并且修改了之前的扩展方法,达到了消耦的目的。

代码2-2

 using BlogCase;
using System.Linq;
namespace BlogCase.Extension
{
public static class ShoppingListExtension
{
public static float Total(this IEnumerable<Commodity> shoppintlist)
{
return shoppintlist.Sum(commodity => commodity.Price);
} public static IEnumerable<Commodity> Filter(this IEnumerable<Commodity> shoppinglist, Func<Commodity, bool> commodityFilter)
{
var commodities = shoppinglist.Where(commodityFilter);
return commodities;
}
}
}

修改后的ShoppingListExtension类中,Total扩展方法的针对的类型变换掉了,而在Filter扩展方法中把返回类型定义为IEnumerable<Commodity>类型,并且定义了一个参数,参数类型为Func<Commodity, bool> 的委托,完全可以用lambda表达式代替,对于lambda的知识后续的篇幅中会有说到。都做了修改后,那我们来看一下测试时的代码。

代码2-3

 using BlogCase.Extension;
namespace BlogCase
{
class Program
{
static void Main(string[] args)
{
ShoppingList shoppinglistTest = new ShoppingList();
shoppinglistTest.Add(new Commodity() { Name = "A", Price = 50.3f });
shoppinglistTest.Add(new Commodity() { Name = "B", Price = });
shoppinglistTest.Add(new Commodity() { Name = "C", Price = 70.9f });
shoppinglistTest.Add(new Commodity() { Name = "D", Price = 80.3f }); Console.WriteLine(shoppinglistTest.Filter(commodity=>commodity.Price>).Total().ToString());
Console.ReadLine();
}
}
}

运行结果如图3

图3

从shoppinglistTest变量调用扩展方法Filter时,传入了一个查询条件(货品加个大于58)这个扩展方法返回的就是上面说的IEnumerable<Commodity>类型,然后紧接着调用IEnumerable<Commodity>类型的扩展方法Total。

到这里简单的一个链式编程模型就出来了,有兴趣的朋友可以接着去深入的了解linq,当然在此之前看完我的后续文章很重要。

作者:金源

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

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

ASP.NET MVC学前篇之扩展方法、链式编程的更多相关文章

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

    ASP.NET MVC学前篇之Ninject的初步了解 1.介绍 废话几句,Ninject是一种轻量级的.基础.NET的一个开源IoC框架,在对于MVC框架的学习中会用到IoC框架的,因为这种IoC开 ...

  2. ASP.NET MVC学前篇之请求流程

    ASP.NET MVC学前篇之请求流程 请求流程描述 对于请求的流程,文章的重点是讲HttpApplication和HttpModule之间的关系,以及一个简单的示例实现.(HttpModule又是M ...

  3. ASP.NET MVC学前篇之Lambda表达式、依赖倒置

    ASP.NET MVC学前篇之Lambda表达式.依赖倒置 前言 随着上篇文章的阅读,可能有的朋友会有疑问,比如(A.Method(xxx=>xx>yy);)类似于这样的函数调用语句,里面 ...

  4. Asp.Net MVC以 JSON传值扩展方法

    Asp.Net在客户端和服务器端,以JSON形式相互传值,可写扩展方法,用到的类型如下: DataContractJsonSerializer类: 该类在System.Runtime.Serializ ...

  5. Asp.Net MVC以JSON传值扩展方法

    Asp.Net在客户端和服务器端,以JSON形式相互传值,可写扩展方法,用到的类型如下: DataContractJsonSerializer类: 该类在System.Runtime.Serializ ...

  6. ASP.NET MVC HtmlHelper 类的扩展方法

    再ASP.NET MVC编程中用到了R语法,在View页面编辑HTML标签的时候,ASP.NET MVC 为我们准备好了可以辅助我们写这些标签的办法,它们就是HtmlHelper.微软官方地址是:ht ...

  7. 第四十一篇、Masonry利用Block实现链式编程

    一直都觉得使用Masonry的时候语法特别优雅,很早的时候就想尝试下怎么实现, 一直都没弄明白,直到最近看见一篇叫block实现链式编程的 1.方法的返回类型是代码块 >代码块的返回类型是该类的 ...

  8. ASP.NET MVC 应用提速的十种方法

    [编者按]本文作者为 DZone 社区的最具价值博主(MVB) Jonathan Danylko,主要介绍为 ASP.NET MVC 应用提速的十种方法.由国内 ITOM 管理平台 OneAPM 编译 ...

  9. 在Asp.Net MVC中用Ajax回调后台方法

    在Asp.Net MVC中用Ajax回调后台方法基本格式: var operData = ...; //传递的参数(action中定义的) var type = ...; //传递的参数(action ...

随机推荐

  1. input=text数字问题

    其实老干部也会犯错,今天朋友在银行卡账号时候要求输入数字,它的正则竟然排除中文.其实正则是很重要的.废话少说.如果禁止中文呢 ime-mode 但是这个方法兼容性并不是很好,首先我们得知道. css ...

  2. Git 创建本地仓库

    前面已经搭好环境了,现在我们缺的是一个管理版本控制的仓库.这次的实验是在电脑本地创建本地仓库.指定路径 默认的位置是在你所安装Git的目录下.Git的仓库你可以建在你电脑的任何目录下(最好不要包含有中 ...

  3. 车销宝无线开单PDA 一款互联网+POS神器 无缝与电脑数据同步 无线POS开单解决方案

    1.无线POS开单解决方案是基于后台系统开发的一套系统,它实现了采购入库退货.销售出库退货.盘点调拨等功能. 2.系统通过(WIFI.GPRS.GSM.蓝牙)实时后台库存.客户.商品.价格跟踪等信息, ...

  4. selenium使用Xpath定位之完整篇

    其中有一片文章提到了xpath元素定位,但是该文章中有些并不能适应一些特殊与个性化的场景.在文本中提供xpath元素的定位终极篇,你一定能在这里找到你需要的解决办法. 第一种方法: 通过绝对路径做定位 ...

  5. shixi

    1. ./statsite -f statsite.conf &(后台): 2. ps ax|grep ** 3. bg fg 4.chmod +x start.sh 5.tcpdump ud ...

  6. OSG消息机制之事件处理概述

    OSG的消息机制包括好多个头文件预定义及多个类. 首先,消息接收相关的类当属osgGA::GUIEventHandler和osgGA::GUIEventAdapter这两个类了.前者处理OSG程序与用 ...

  7. 关闭rdlc报表打印预览后,关闭客户端,抛出异常“发生了应用程序级的异常 将退出”

    问题:关闭rdlc报表打印预览后,关闭客户端,抛出异常“发生了应用程序级的异常 将退出” 办法:在容纳ReportViewer的窗体后台代码中,添加如下代码即可 protected override ...

  8. 530 User cannot log in, home directory inaccessible.

    服务器是winserver,控制面板-用户账号里新建了一个Ftp账户用来做ftp连接.可在本地连接FTP总提示530 User cannot log in, home directory inacce ...

  9. BZOJ3197 & 组合乱搞

    Description    求\[\sum_{i = 1}^{n}i^m m^i , m \leq 1000 \] 的值.Solution    From Miskcoo's Space:      ...

  10. [JSOI2008]完美的对称 题解

    题目大意: 首先我们给定一点A以及对称中心S,点A'是点A以S为对称中心形成的像点,即点S是线段AA'的对称中心. 点阵组(X)以S为中心的像点是由每个点的像点组成的点阵组.X是用来产生对称中心S的, ...