<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_Catcher In The Rye</title><subtitle type="text"/><id>http://feed.cnblogs.com/blog/u/18870/rss</id><updated>2012-05-10T09:16:36Z</updated><author><name>alby</name><uri>http://www.cnblogs.com/alby/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/alby/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/18870/rss"/><entry><id>http://www.cnblogs.com/alby/archive/2011/09/21/xoohoo-init.html</id><title type="text">Xoohoo系列(二)：初始化配置、加载模块或后台服务</title><summary type="text">从开发的角度讲，Global.asax文件是基于ASP.NET 应用程序的入口，而Application_Start方法正是一切的开始。 链接：IIS 5.0 和 6.0 的 ASP.NET 应用程序生命周期概述 Xoohoo实现了一个XoohooApplication类，其继承自HttpApplication。而XoohooApplication类供Global.asax来继承。 XoohooApplication类的Application_Start方法会完成两大工作。 一、初始化配置 1、设置IoC/DI容器。我们知道，虽然MVC3提供了依赖注入的支持，但并没有一个严格意义...</summary><published>2011-09-21T06:42:00Z</published><updated>2011-09-21T06:42:00Z</updated><author><name>alby</name><uri>http://www.cnblogs.com/alby/</uri></author><link rel="alternate" href="http://www.cnblogs.com/alby/archive/2011/09/21/xoohoo-init.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/alby/archive/2011/09/21/xoohoo-init.html"/><content type="html">&lt;p&gt;从开发的角度讲，Global.asax文件是基于ASP.NET 应用程序的入口，而Application_Start方法正是一切的开始。    &lt;br /&gt;链接：&lt;a href="http://msdn.microsoft.com/zh-cn/library/ms178473.aspx" target="_blank"&gt;IIS 5.0 和 6.0 的 ASP.NET 应用程序生命周期概述&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Xoohoo实现了一个XoohooApplication类，其继承自HttpApplication。而XoohooApplication类供Global.asax来继承。&lt;/p&gt;  &lt;p&gt;XoohooApplication类的Application_Start方法会完成两大工作。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;一、初始化配置&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;1、设置&lt;a href="http://zh.wikipedia.org/wiki/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC" target="_blank"&gt;IoC/DI&lt;/a&gt;容器。我们知道，虽然MVC3提供了依赖注入的支持，但并没有一个严格意义上的DI容器,其内部创建对象是通过实现自&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.mvc.idependencyresolver%28v=VS.98%29.aspx" target="_blank"&gt;IDependencyResolver&lt;/a&gt;接口的私有类DefaultDependencyResolver。具体点就是GetService和GetServices方法。GetService方法调用&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.activator.createinstance.aspx" target="_blank"&gt;Activator.CreateInstance&lt;/a&gt;会创建对象，要求类型定义必须提供无参的构造函数，而GetServices方法只会返回一个空的迭代器Enumerable.Empty&amp;lt;object&amp;gt;()。     &lt;br /&gt;Xoohoo提供了一个间接实现自IDependencyResolver接口的UnityDependencyInjector类。通过&lt;a href="http://msdn.microsoft.com/zh-cn/library/gg401909%28v=VS.98%29.aspx" target="_blank"&gt;DependencyResolver.SetResolver&lt;/a&gt;方法，将DefaultDependencyResolver替换为UnityDependencyInjector。    &lt;br /&gt;UnityDependencyInjector 采用对象&lt;a href="http://zh.wikipedia.org/wiki/%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F" target="_blank"&gt;适配器模式&lt;/a&gt;对&lt;a href="http://unity.codeplex.com/" target="_blank"&gt;Unity&lt;/a&gt;容器进行了包装 。它直接实现自Xoohoo的IDependencyInjector接口，而后者继承自IDependencyResolver。IDependencyInjector接口提供了一种在运行时(Runtime)进行映射注册的机制。当然如果您不喜欢用Unity,可以实现自己的DI容器，如AutofacDependencyInjector，Xoohoo提供了相关机制允许您做这样的替换；     &lt;br /&gt;UnityDependencyInjector除了创建容器外，还会完成一些类型注册的工作。     &lt;br /&gt;2、注册FilterProvider。将Xoohoo提供的FilterRegistryFilterProvider添加到&lt;a href="http://msdn.microsoft.com/zh-cn/library/gg416532%28v=VS.98%29.aspx" target="_blank"&gt;FilterProviders.Providers&lt;/a&gt;中。     &lt;br /&gt;如果想要使用基于外部配置的Filter注册解决方案，FilterRegistryFilterProvider将是一个不错的选择。     &lt;/p&gt;&lt;div&gt;&lt;div&gt;3、注册ActionInvoker。将XoohooControllerActionInvoker注册入DI容器。  &lt;br /&gt;XoohooControllerActionInvoker继承自&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.mvc.controlleractioninvoker.aspx" target="_blank"&gt;ControllerActionInvoker&lt;/a&gt;类并重写了&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.mvc.controlleractioninvoker.createactionresult.aspx" target="_blank"&gt;CreateActionResult&lt;/a&gt;方法，目的是为了让Action支持更丰富的返回值类型。  &lt;br /&gt;Controller的&lt;a href="http://msdn.microsoft.com/zh-cn/library/dd505131%28v=VS.98%29.aspx" target="_blank"&gt;ActionInvoker&lt;/a&gt;属性一般会返回一个ControllerActionInvoker实例，在DependencyInjectorControllerFactory中将设置Controller的ActionInvoker为XoohooControllerActionInvoker，这也正是使用DependencyInjectorControllerFactory的目的。&lt;br /&gt;4、设置控制器工厂。通过&lt;a href="http://msdn.microsoft.com/zh-cn/library/dd460275" target="_blank"&gt;ControllerBuilder.Current.SetControllerFactory&lt;/a&gt;方法，使用DependencyInjectorControllerFactory类替换MVC内置的&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.mvc.defaultcontrollerfactory.aspx" target="_blank"&gt;DefaultControllerFactory&lt;/a&gt;类。&lt;/div&gt;&lt;/div&gt;DefaultControllerFactory创建的Controller实例，将不会设置其&lt;a href="http://msdn.microsoft.com/zh-cn/library/dd505131%28v=VS.98%29.aspx" target="_blank"&gt;ActionInvoker&lt;/a&gt;属性，所以在第一次从ActionInvoker取值时，将创建一个&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.mvc.controlleractioninvoker.aspx" target="_blank"&gt;ControllerActionInvoker&lt;/a&gt;实例并返回。在DependencyInjectorControllerFactory中将其设置为XoohooControllerActionInvoker，从外部&amp;#8220;看起来&amp;#8221;Controller的ActionInvoker被替换了。     &lt;br /&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;二、加载模块及后台服务&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;我们知道，想要在开机后运行某些程序，我们可以用注册表或&amp;#8220;开始菜单-&amp;gt;程序-&amp;gt;启动&amp;#8221;等方式添加要启动的程序信息。总有一种机制来保证来读取注册表或启动菜单并完成启动吧？对于Xoohoo来说，这就是引导程序。创建一个新的模块或后台服务后，在Xoohoo.config（位于站点的Configs目录，也可以自行修改配置文件名或路径）对其进行配置，引导程序负责它们的加载工作。&lt;/p&gt;  &lt;p&gt;1、模块或后台服务配置&lt;/p&gt;  &lt;p&gt;模块或后台服务设计完成后，将其配置在Xoohoo.config文件中。    &lt;br /&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211418496257.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211419187298.png" border="0" height="288" width="557" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;上图是模块的配置，比如上面有名称为Core、Skinning和Logging等模块。只需要配置名称和模块，如果模块有私有配置，也加上去。    &lt;br /&gt;    &lt;br /&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211419192531.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/20110921141925966.png" border="0" height="93" width="644" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;上图是后台服务的配置，比如上面有一个名称为MailMessageService的模块。除了配置名称和服务类型外，还需要加上服务执行器的类型(executorType),以及执行的时间间隔(interval)。InProcessBackgroundServiceExecutor是Xoohoo内置的服务执行器，它内部使用一个Timer来控制服务的执行。&lt;/p&gt;  &lt;p&gt;2、引导程序&lt;/p&gt;  &lt;p&gt;引导程序指实现了IBootStrapperTask接口的类。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211419283733.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211419361238.png" border="0" height="327" width="502" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;模块或后台服务在Xoohoo.config配置后，在程序启动时将由引导程序来加载。    &lt;br /&gt;Xoohoo内置了两种引导程序，LoadModules和LoadBackgroundServices，两者的关系就像windows的注册表和启动菜单的关系。模块由LoadModules类来加载，而后台服务则由LoadBackgroundServices类来加载。&lt;/p&gt;  &lt;p&gt;我们在DI容器中(UnityDependencyInjector)对这两个引导程序进行了注册。 &lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211420206823.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211420227497.png" border="0" height="88" width="660" /&gt;&lt;/a&gt;&amp;nbsp; &lt;br /&gt;    &lt;br /&gt;Application_Start方法会调用Load方法会获取引导程序并控制其执行。     &lt;br /&gt;    &lt;br /&gt;&amp;nbsp;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211421371732.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/20110921142532598.png" border="0" height="307" width="660" /&gt;&lt;/a&gt;     &lt;br /&gt;    &lt;br /&gt;一般将具有UI界面，需要路由信息、配置ModelBinder等的插件，做成一个模块(Module)。当然，无UI的插件也可以做成模块的形式，比如日志、缓存等模块;     &lt;br /&gt;如果需要定时完成一些任务，比如每隔5分钟邮件报告一次服务器资源情况，就做成一个后台服务(BackgroundService)。 当然，一次行的操作也可以做成服务。&lt;/p&gt;  &lt;p&gt;2、加载模块&lt;/p&gt;  &lt;p&gt;模块是一个实现了IModule接口的类，接口定义如下：    &lt;br /&gt;    &lt;br /&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/20110921142619105.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211426304522.png" border="0" height="471" width="660" /&gt;&lt;/a&gt; &lt;/p&gt;          &lt;p&gt;LoadModules类用于加载模块，其核心方法是Execute：    &lt;br /&gt;&amp;nbsp;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211428377387.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/20110921143256156.png" border="0" height="463" width="660" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;moduleRegistry 对应的是模块注册器ModuleRegistry实例，用于保存已经加载的模块。这种映射关系在UnityDependencyInjector进行的，保存的是一个单例。模块注册器将在紧接着的下面介绍；    &lt;br /&gt;routes对应的是System.Web.Mvc.RouteTable.Routes；     &lt;br /&gt;modelBinders对应的是System.Web.Mvc.ModelBinders.Binders；     &lt;br /&gt;moduleConfig对应的是Xoohoo.config的配置文件的反序列化结果；     &lt;br /&gt;globalFilters对应的是System.Web.Mvc.GlobalFilters.Filters;     &lt;br /&gt;filterRegistry对应的是Xoohoo.FilterProviders.FilterRegistry.Filters。     &lt;br /&gt;这些对象都是单例。&lt;/p&gt;  &lt;p&gt;调用routes、globalFilters和filterRegistry的将其清空。    &lt;br /&gt;然后遍历Xoohoo.config中的模块设置，通过moduleRegistry.Load进行加载并返回Module的实例。     &lt;br /&gt;如果成功创建模块，则依次调用模块的Initialize、RegisterModelBinders和RegisterRoutes等方法。将路由配置注册入MVC中的路由表中，将Filter过滤器注册入MVC的&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.mvc.globalfilters.filters%28v=VS.98%29.aspx" target="_blank"&gt;GlobalFilters.Filters&lt;/a&gt;或FilterRegistryFilterProvider中，将模型绑定器注册入&lt;a href="http://msdn.microsoft.com/zh-cn/library/dd460298.aspx" target="_blank"&gt;ModelBinders.Binders&lt;/a&gt;中。 &lt;/p&gt;  &lt;p&gt;moduleRegistry.RegisterFilters是一个扩展方法，内部调用的是Module的RegisterFilters方法。将其放在foreach外部是希望所有路由配置都加入的情况下,再注册Filter。因为Xoohoo提供了一种可以根据Route数据设置Filter的机制，避免创建Filter的时候由于Route不存在而导致失败。&lt;/p&gt;&lt;p&gt;3、模块注册表 (ModuleRegistry) &lt;/p&gt;  &lt;p&gt;模块注册表用于注册(ModuleRegistry.Load方法)和保存模块引用。    &lt;br /&gt;ModuleRegistry.Load方法，根据Xoohoo.config模块配置中模块的类型，创建模块的实例。并将模块本身的一些私有配置(Settings)存入模块实例中。将模块实例的引用存入ModuleRegistry的内部容器中，然后返回模块的实例。     &lt;br /&gt;    &lt;br /&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211434556388.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211435048528.png" border="0" height="447" width="660" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;另注：ModuleRegistry.Load方法还会根据模块DataProvider的配置进行相关设置，这里暂时略去。&lt;/p&gt;  &lt;p&gt;4、加载后台服务&lt;/p&gt;  &lt;p&gt;后台服务是一个实现了IBackgroundService接口的类，接口定义如下：    &lt;br /&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211435155703.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/20110921143726123.png" border="0" height="151" width="335" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;后台服务有对应的后台服务执行器（BackgroundServiceExecutor）负责服务的调度执行。后台服务执行器指实现了IBackgroundServiceExecutor接口的类，接口定义如下：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211437388312.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211438079320.png" border="0" height="127" width="382" /&gt;&lt;/a&gt;&amp;nbsp; &lt;/p&gt;  &lt;p&gt;LoadBackgroundServices类用于加载模块，其核心方法是Execute：    &lt;br /&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211439268000.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211440052129.png" border="0" height="217" width="660" /&gt;&lt;/a&gt;&amp;nbsp; &lt;/p&gt;  &lt;p&gt;与模块注册表类似，backgroundServicesRegistry对应的是后台服务注册表BackgroundServiceRegistry实例，后台服务注册表并不是用于保存后台服务本身，而是用于保存已经加载的后台&amp;#8220;后台服务执行器(BackgroundServiceExecutor)&amp;#8221;实例的引用（执行器包含&amp;#8220;后台服务&amp;#8221;的引用）。BackgroundServiceRegistry的映射关系在UnityDependencyInjector进行的，保存的是一个单例；    &lt;br /&gt;moduleConfig对应的是Xoohoo.config的配置文件的反序列化结果。 &lt;/p&gt;  &lt;p&gt;Execute方法遍历Xoohoo.config中的后台服务配置，通过backgroundServicesRegistry.Add对&amp;#8220;后台服务执行器&amp;#8221;进行加载并注册。接着调用对应的后台服务执行器将服务启动(Start)。&lt;/p&gt;  &lt;p&gt;LoadBackgroundServices比较简单，具体的包括实体化后台服务及其执行器，将在接下来要介绍的BackgroundServiceRegistry类中进行。&lt;/p&gt;  &lt;p&gt;5、后台服务注册表(BackgroundServiceRegistry)&lt;/p&gt;  &lt;p&gt;如上所述，后台服务注册表并不是用于保存后台服务本身，而是用于加载和保存&amp;#8220;后台服务执行器(BackgroundServiceExecutor)&amp;#8221;，具体操作在其BackgroundServiceRegistry.Add方法中。 &lt;/p&gt;  &lt;p&gt;Add方法根据Xoohoo.config配置中&amp;#8220;后台服务&amp;#8221;的类型(type)以及&amp;#8220;后台服务执行器&amp;#8221;类型(exectorType)，创建&amp;#8220;后台服务&amp;#8221;的实例和&amp;#8220;后台服务执行器&amp;#8221;的实例。并将一些私有配置(Settings)存入后台服务中。然后将&amp;#8220;后台服务执行器&amp;#8221;放入BackgroundServiceRegistry的内部容器中。 &lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/20110921144109277.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211441122521.png" border="0" height="239" width="660" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;6、后台服务执行器(BackgroundServiceExecutor)&lt;/p&gt;  &lt;p&gt;创建后台服务执行器时候，后台服务实例会作为参数传给其构造函数。    &lt;br /&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211441178961.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211441186321.png" border="0" height="59" width="660" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Xoohoo内置了一个InProcessBackgroundServiceExecutor执行器。当调用执行器的Start方法是，会完成后台服务的第一次执行，之后根据配置中的时间间隔再次执行。具体的请看InProcessBackgroundServiceExecutor类的源码。&lt;/p&gt;  &lt;p&gt;Xoohoo中有一系列的内置模块和后台服务，以后将有专门的篇幅加以介绍。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/alby/aggbug/2183980.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/alby/archive/2011/09/21/xoohoo-init.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/alby/archive/2011/09/21/xoohoo-summary.html</id><title type="text">Xoohoo系列(一)：概述</title><summary type="text">作为一个开发者，我们免不了要做很多重复的事情。我们不只在重复别人造轮子，也在重复自我浪费时间——我们应该有一种罪恶感。庆幸的是很多人在帮助我们尽可能的减少这种重复，他们提出或总结了很多的宝贵的思想，开发了很多的有用的开发辅助工具。比如设计模式、类库、O/RM，代码生成器，以及更具体的CMS(Content Management System)等等。设计模式让我们在设计思想得到一定程度的解放，在设计方向上给予指引。这就像乘法口诀表，不用我们算个简单的3721还需要掰手指头；类库如.Net的BCL(Base Class Library)、FCL(Framework Class Library)等，</summary><published>2011-09-21T03:42:00Z</published><updated>2011-09-21T03:42:00Z</updated><author><name>alby</name><uri>http://www.cnblogs.com/alby/</uri></author><link rel="alternate" href="http://www.cnblogs.com/alby/archive/2011/09/21/xoohoo-summary.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/alby/archive/2011/09/21/xoohoo-summary.html"/><content type="html">&lt;p&gt;作为一个开发者，我们免不了要做很多重复的事情。我们不只在重复别人造轮子，也在重复自我浪费时间&amp;#8212;&amp;#8212;我们应该有一种罪恶感。庆幸的是很多人在帮助我们尽可能的减少这种重复，他们提出或总结了很多的宝贵的思想，开发了很多的有用的开发辅助工具。比如&lt;a href="http://zh.wikipedia.org/wiki/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F_%28%E8%AE%A1%E7%AE%97%E6%9C%BA%29" target="_blank"&gt;设计模式&lt;/a&gt;、类库、&lt;a href="http://zh.wikipedia.org/wiki/%E5%AF%B9%E8%B1%A1%E5%85%B3%E7%B3%BB%E6%98%A0%E5%B0%84" target="_blank"&gt;O/RM&lt;/a&gt;，代码生成器，以及更具体的&lt;a href="http://zh.wikipedia.org/wiki/%E5%86%85%E5%AE%B9%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F" target="_blank"&gt;CMS&lt;/a&gt;(Content Management System)等等。设计模式让我们在设计思想得到一定程度的解放，在设计方向上给予指引。这就像乘法口诀表，不用我们算个简单的3721还需要掰手指头；类库如.Net的BCL(Base Class Library)、FCL(Framework Class Library)等，以官方发布的形式将一些常用的功能进行了封装。当然，还有公司的类库或自己的私房类库；O/RM让我们在领域模型和关系数据库的映射上提高开发效率。据统计如果不使用O/RM，在映射方面需要花去总体开发时间的30%-40%；代码生成器则是将有规律的集中的重复的工作交给程序来处理；CMS在应用的层次上减少了重复工作，比如&lt;a href="http://wordpress.org/" target="_blank"&gt;Wordpress&lt;/a&gt;,&lt;a href="http://www.dotnetnuke.com/" target="_blank"&gt;DotNetNuke&lt;/a&gt;等。&lt;/p&gt;  &lt;p&gt;Xoohoo又试图解决哪些方面的问题呢？&lt;/p&gt;  &lt;p&gt;Xoohoo基于&lt;a href="http://www.asp.net/mvc" target="_blank"&gt;ASP.NET MVC&lt;/a&gt;（以下简称MVC）3的框架，其前身是微软的开源项目&lt;a href="http://oxite.codeplex.com/" target="_blank"&gt;Oxite&lt;/a&gt;。遗憾的是后者停止了开发目前还停留在MVC 1。庆幸的微软提供了另一个开源项目&lt;a href="http://orchard.codeplex.com/" target="_blank"&gt;Orchard&lt;/a&gt;供我们选择，&lt;a href="http://www.cnblogs.com/esshs/"&gt;二十四画生&lt;/a&gt;对Orchard颇有研究。不管是Oxite还是Orchard,他们从一开始就试图给用户提供一个可用的产品(Blog，但不仅限于此)，并提供了超强的扩展性。&lt;/p&gt;  &lt;p&gt;Xoohoo的目的不是要给您一个现成的产品，而是一个轻量开发框架,旨在能为您减少那么一点点重复的工作。如果您开发一个新的基于MVC的项目，希望您能试试。&lt;/p&gt;  &lt;p&gt;您首先可以将之看作是一个类库，对MVC 3进行了扩充。它借鉴并使用了一些优秀博文或开源项目的代码。由于资料比较零散，不再列出，在此一并表示感谢；其次将之作为一个小框架，在此基础您可以开发自己的模块(插件)，并能进行无缝整合。如果愿意，您还可以将某些模块拿出来分享。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;一、Xoohoo是一个ASP.NET MVC 3的扩展类库&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;将Xoohoo作为一个类库，我相信您总等找到您所需要的。&lt;/p&gt;  &lt;p&gt;1、ActionFilter&lt;/p&gt;  &lt;p&gt;Xoohoo内置了若干的AtionFilter,包括TimerActionFilter、CompressActionFilter、ErrorExceptionFilter以及各种的AuthorizationFilter。&lt;/p&gt;  &lt;p&gt;TimerActionFilter能计算Action的执行时间：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211138569181.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/20110921113937919.png" border="0" height="93" width="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;CompressActionFilter能对输出进行压缩(gzip,deflate)。    &lt;br /&gt;ErrorExceptionFilter类似于MVC内置的HandleErrorAttribute，配合Xoohoo内置的日志模块，可以进行日志记录；配合Xoohoo的皮肤模块，错误提示View还可以换肤。     &lt;br /&gt;各种的AuthorizationFilter提供了非常灵活的授权(权限)认证，以后会有专门的篇幅加以介绍。&lt;/p&gt;  &lt;p&gt;2、ActionInvoker&lt;/p&gt;  &lt;p&gt;XoohooControllerActionInvoker重写了MVC内置的&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.mvc.controlleractioninvoker.aspx" target="_blank"&gt;ControllerActionInvoker&lt;/a&gt;的&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.mvc.controlleractioninvoker.createactionresult" target="_blank"&gt;CreateActionResult&lt;/a&gt;等方法,使其支持AJAX请求，以及更灵活的Action返回值类型。&lt;/p&gt;  &lt;p&gt;比如有Action:&lt;/p&gt;  &lt;div style="border: 1px solid silver; text-align: left; padding: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text;" id="codeSnippetWrapper"&gt;   &lt;div style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible;" id="codeSnippet"&gt;     &lt;span style="color: #606060;" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; ActionResult List()&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum3"&gt;   3:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; View(new List&amp;lt;Article&amp;gt;());&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum4"&gt;   4:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;如果是AJAX请求，您需要在重新实现一个Action，或者在Action内部进行一次判断：&lt;/p&gt;&lt;div style="border: 1px solid silver; text-align: left; padding: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text;" id="codeSnippetWrapper"&gt;  &lt;div style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible;" id="codeSnippet"&gt;    &lt;span style="color: #606060;" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; ActionResult List() &lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum2"&gt;   2:&lt;/span&gt; {   &lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;(Request.IsAjaxRequest())&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum4"&gt;   4:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; Json(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; List&amp;lt;Article&amp;gt;());&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum6"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; View(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; List&amp;lt;Article&amp;gt;());&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum7"&gt;   7:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum8"&gt;   8:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;如果使用XoohooControllerActionInvoker，只需要这样写：&lt;/p&gt;&lt;div style="border: 1px solid silver; text-align: left; padding: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text;" id="codeSnippetWrapper"&gt;  &lt;div style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible;" id="codeSnippet"&gt;    &lt;span style="color: #606060;" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; List&amp;lt;Article&amp;gt; List() &lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; List&amp;lt;Article&amp;gt;();&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum4"&gt;   4:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;MVC内置的ControllerActionInvoker，如果Action返回的不是一个&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.mvc.actionresult.aspx" target="_blank"&gt;ActionResult&lt;/a&gt;类型的值，将会调用&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.convert.tostring%28VS.80%29.aspx" target="_blank"&gt;Convert.ToString&lt;/a&gt;方法生成其字符串形式，再使用字符串生成一个&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.mvc.contentresult.aspx" target="_blank"&gt;ContentResult&lt;/a&gt;。   &lt;br /&gt;XoohooControllerActionInvoker也会根据Action返回值的类型进行判断。   &lt;br /&gt;如果是简单类型，如int,string等,则采用ControllerActionInvoker相同的方式，即调用Convert.ToString方法生成其字符串形式，再使用字符串生成一个ContentResult。   &lt;br /&gt;如果是复杂类型，则进行进一步判断是否是AJAX请求。如果是，将生成一个JsonResult并将Action返回值赋给JsonResult的Data属性；否则将返回值赋给Controller的ViewData的Model属性，然后生成一个ViewResult。   &lt;br /&gt;怎么样，是不是很灵活很简洁？&lt;/p&gt;&lt;p&gt;3、ActionResult&lt;/p&gt;&lt;p&gt;Xoohoo扩充了一些ActionResult,如RssResult、XmlResult等，比较简单不再累述。&lt;/p&gt;&lt;p&gt;4、ControllerFactory&lt;/p&gt;&lt;p&gt;ControllerFactory是用于查找Controller类型并创建Controller实例的。一般我们不需要改变查找Controller类型的方式。在MVC3中，至少有两种途径可以改变创建Controller实例方式，一是自定义ControllerFactory；二是重新实现一个IControllerActivator，在实例化&lt;a href="http://msdn.microsoft.com/zh-cn/library/gg416592%28v=VS.98%29.aspx" target="_blank"&gt;DefaultControllerFactory&lt;/a&gt;时作为构造函数参数传递进去。&lt;/p&gt;&lt;p&gt;Xoohoo选择了前者，实现了一个DependencyInjectorControllerFactory类。因为在创建Controller实例后，还需要重新设置Controller的ActionInvoker。其实这正是DependencyInjectorControllerFactory类存在的意义。&lt;/p&gt;&lt;p&gt;备注：在MVC2中，仅仅想要在创建Controller获取&lt;a href="http://zh.wikipedia.org/wiki/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC" target="_blank"&gt;IoC/DI&lt;/a&gt;容器的支持,就需要自定义ControllerFactory。这在MVC3已经不是必需的，只需要创建一个容器类实现&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.mvc.idependencyresolver%28v=VS.98%29.aspx" target="_blank"&gt;IDependencyResolver&lt;/a&gt;接口，然后在Global.asax中调用&lt;a href="http://msdn.microsoft.com/zh-cn/library/gg401985%28v=VS.98%29.aspx" target="_blank"&gt;DependencyResolver.SetResolver&lt;/a&gt;方法即可。&lt;/p&gt;&lt;p&gt;5、ModelBinders&lt;/p&gt;&lt;p&gt;&lt;a href="http://msdn.microsoft.com/zh-cn/library/dd470193.aspx" target="_blank"&gt;DefaultModelBinder&lt;/a&gt;是非常强大的，或者是一个重量级的。如果想要稍微提供模型绑定的效率，或想要绑定更可控，就用自定义ModelBinder。Xoohoo增加了几个ModelBinder，包括GuidListModelBinder、Int32ListModelBinder、PagingInfoModelBinder、IPAddressModelBinder等。通过名称就可以看出它们的作用。&lt;/p&gt;&lt;p&gt;6、ValidationAttribute&lt;/p&gt;&lt;p&gt;MVC3的数据校验机制非常好用，只需一处设置，可以为您生成客户端校验脚本(如果开启Unobtrusive，则会生成html attributes)，并支持服务器端验证。&lt;/p&gt;&lt;p&gt;Xoohoo扩展了几个常用的正则验证，如Email,Url,IP等；并提供一个比较验证CompareAttribute，可以进行日期、数字等类型的&amp;gt;、&amp;lt;、&amp;gt;=、&amp;lt;=、!=等比较，而MVC3内置的比较验证只能比较是否相等。   &lt;br /&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211139411362.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211140075830.png" border="0" height="148" width="396" /&gt;&lt;/a&gt;   &lt;br /&gt;  &lt;br /&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211140104911.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211140178678.png" border="0" height="130" width="580" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;7、RouteConstraint&lt;/p&gt;&lt;p&gt;Xoohoo同样提供一些常用的路由规则，如IsInt、IsLong、IsGuid等，他们实现自&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.routing.irouteconstraint.aspx" target="_blank"&gt;IRouteConstraint&lt;/a&gt;接口。（随便提一下，与路由相关的，在老赵提供的&lt;a href="http://blog.zhaojie.me/2009/08/url-routing-with-domain.html" target="_blank"&gt;子域名解决方案&lt;/a&gt;基础上进行了扩展完善）&lt;/p&gt;&lt;p&gt;8、FilterProvider&lt;/p&gt;&lt;p&gt;MVC提供了一种&lt;a href="http://zh.wikipedia.org/wiki/AOP" target="_blank"&gt;AOP&lt;/a&gt;(面向侧面的程序设计)的编程模式，我们可以为Controller或Action设置各种Filter,包括ActionFilter、ResultFilter、ExceptionFilter、AuthorizationFilter，在一定的阶段将执行这些Filter。关于Filter的执行流程，可以看看xfrog这篇图文并茂的&lt;a href="http://www.cnblogs.com/xfrog/archive/2010/12/29/1921134.html" target="_blank"&gt;博文&lt;/a&gt;。&lt;/p&gt;&lt;p&gt;MVC3提供了三种FilterProvider，它们提供了设置或获取Filter的方式，相较于MVC2，这又是一个扩展点。包括：&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.mvc.globalfiltercollection%28v=VS.98%29.aspx" target="_blank"&gt;GlobalFilterCollection&lt;/a&gt;、&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.mvc.filterattributefilterprovider%28v=VS.98%29.aspx" target="_blank"&gt;FilterAttributeFilterProvider&lt;/a&gt; 和&lt;a href="http://msdn.microsoft.com/zh-cn/library/gg402087%28v=VS.98%29.aspx" target="_blank"&gt;ControllerInstanceFilterProvider&lt;/a&gt;。   &lt;br /&gt;GlobalFilterCollection可以通过&lt;a href="http://msdn.microsoft.com/zh-cn/library/gg402089%28v=VS.98%29.aspx" target="_blank"&gt;GlobalFilters.Filters&lt;/a&gt;静态属性访问，用户增添全局的，作用于所有Controller的所有Action的Filter;   &lt;br /&gt;FilterAttributeFilterProvider用于获取基于Attribute的Filter;   &lt;br /&gt;ControllerInstanceFilterProvider用于获取Controller实例Filter（Controller实现了IActionFilter等接口，其本身就是一个Filter）。&lt;/p&gt;&lt;p&gt;Xoohoo提供了一种基于外部配置的Filter获取方式：FilterRegistryFilterProvider。可以设置某些Controller具有某些Filter，也可以设置某些(不是全部)Action具有某些Filter。还可以某些Route或具体有某些RouteValue,DataToken(如Area)的路由具有某些Filter（如果您愿意，还可以根据cookie值来配置）。它还有个优点就是能将Filter像Golbal Filters一样缓存起来，不用像Attribute形式的Filter那样使用时还得通过反射从元数据中获取并进行反序列化。   &lt;br /&gt;可以通过FilterRegistry.Filters静态属性添加Filter,这和GlobalFilters.Filters也类似。&lt;/p&gt;&lt;p&gt;9、Extensions&lt;/p&gt;&lt;p&gt;Extensions就是一些扩展方法集。   &lt;br /&gt;Xoohoo为了支持更多的需求，几乎扩展了MVC3内置的相关的所有HtmlHelper、UrlHelper相关的扩展方法，用于支持如二（多）级域名、更丰富的HtmlHelper、UrlHelper等。当然还有一些零散而好用的扩展就不一一列出。更丰富的扩展方法可以看看&lt;a href="http://www.cnblogs.com/ldp615/"&gt;鹤冲天&lt;/a&gt;的相关博文。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;二、Xoohoo是一个框架&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Xoohoo作为一个框架，它支持插拔式的模块（插件）开发方式；内置有&lt;a href="http://zh.wikipedia.org/wiki/%E4%BB%A5%E8%A7%92%E8%89%B2%E7%82%BA%E5%9F%BA%E7%A4%8E%E7%9A%84%E5%AD%98%E5%8F%96%E6%8E%A7%E5%88%B6" target="_blank"&gt;RBAC&lt;/a&gt;(Role-Based Access Control)模块，日志模块，缓存模块，并皆可替换；支持&lt;a href="http://zh.wikipedia.org/wiki/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC" target="_blank"&gt;IoC/DI&lt;/a&gt;；&lt;/p&gt;&lt;p&gt;开发一个新的模块非常简单，只需要实现一个接口，并在配置文件中增加模块的配置即可。&lt;/p&gt;&lt;p&gt;1、什么叫Xoohoo的模块(Module)&lt;/p&gt;&lt;p&gt;我们约定，实现了IModule接口的类称为模块。接口定义：&lt;/p&gt;&lt;div style="border: 1px solid silver; text-align: left; padding: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text;" id="codeSnippetWrapper"&gt;  &lt;div style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible;" id="codeSnippet"&gt;    &lt;span style="color: #606060;" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;interface&lt;/span&gt; IModule&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// 模块名称&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; ModuleName { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// 模块设置&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum10"&gt;  10:&lt;/span&gt;     AppSettingsHelper Settings { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum11"&gt;  11:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum12"&gt;  12:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// 初始化模块&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum13"&gt;  13:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum14"&gt;  14:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Initialize();&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum15"&gt;  15:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum16"&gt;  16:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// 注册路由配置&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum17"&gt;  17:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum18"&gt;  18:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; RegisterRoutes();&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum19"&gt;  19:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum20"&gt;  20:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// 注册过滤器&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum21"&gt;  21:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum22"&gt;  22:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;param name="filterRegistry"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum23"&gt;  23:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;param name="globalFilters"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum24"&gt;  24:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; RegisterFilters(FilterRegistryFilterProvider filterRegistry, GlobalFilterCollection globalFilters);&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum25"&gt;  25:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum26"&gt;  26:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// 注册模型绑定器&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum27"&gt;  27:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum28"&gt;  28:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;param name="modelBinders"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum29"&gt;  29:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; RegisterModelBinders(ModelBinderDictionary modelBinders);&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum30"&gt;  30:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum31"&gt;  31:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// 卸载模块&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum32"&gt;  32:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum33"&gt;  33:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Unload();&lt;!--CRLF--&gt;    &lt;span style="color: #606060;" id="lnum34"&gt;  34:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;模块包括模块名称（ModuleName）、模块设置（Settings）、初始化方法（Initialize）、注册路由方法（RegisterRoutes）、注册过滤器方法（RegisterFilters）、注册模型绑定器方法（RegisterModelBinders）、卸载模块方法（Unload）。Xoohoo提供了一个实现了IModule接口的抽象类Module，一般情况下，我们建议你在设计新的模块时，实现抽象类Module而不是IModule接口，这样会让您开放起来更简单。&lt;/p&gt;&lt;p&gt;2、模块的配置&lt;/p&gt;&lt;p&gt;模块开发完成后，只需要将模块配置入Xoohoo.config即可生效。修改Xoohoo.config会导致AppDomain回收，所以不用去手工重动站点。当然，如果涉及数据库建表之类的操作，暂时还得您自己手工处理。   &lt;br /&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211141284181.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/alby/201109/201109211141392153.png" border="0" height="342" width="654" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;3、模块的加载&lt;/p&gt;&lt;p&gt;当网站接收到第一次请求时，将会读取模块配置文件Xoohoo.config(位于站点的Configs目录，可自行更改)。获取模块的类型，创建模块的实例，依次调用模块的几个注册方法，将路由配置、Filter过滤器、模型绑定器配置加入MVC中。&lt;br /&gt;更详细的关于模块定义及加载的内容，以及Xoohoo内置的几个模块的介绍，将放在之后的博文中。&lt;/p&gt;&lt;p&gt;4、后台服务的加载&lt;br /&gt;后台服务是一个实现了IBackgroundService接口的类，它有对应的后台服务执行器（BackgroundServiceExecutor）负责服务的调度执行。&lt;br /&gt;&lt;/p&gt;&lt;p&gt;如果要定时完成一些任务，如邮件报告服务器资源信息，则可以定义一些后台服务。它的加载方式类似于模块的加载，并在模块加载完毕之后加载。&lt;br /&gt;更详细的关于后台服务定义及加载的内容，将放在之后的博文中。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/alby/aggbug/2183730.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/alby/archive/2011/09/21/xoohoo-summary.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/alby/archive/2011/03/30/aspdotnet-mvc-update-3.html</id><title type="text">ASP.NET MVC 3 RTM 更新(3)</title><summary type="text">五、SessionStateAttribute构造SessionStateAttribute对象时必须传入一个SessionStateBehavior枚举值，通过Attribute的Behavior属性可以获取该值。该Attribute只能用于引用类型(AttributeTargets.Class)，不允许重复使用(AllowMultiple=false),允许继承(Inherited=true)。六、MvcRouteHandlerMvcRouteHandler类增加了一个接受IControllerFactory接口实现类的对象作为参数传的构造方法，构造对象允许传入null值。而构造方法内部只</summary><published>2011-03-30T05:10:00Z</published><updated>2011-03-30T05:10:00Z</updated><author><name>alby</name><uri>http://www.cnblogs.com/alby/</uri></author><link rel="alternate" href="http://www.cnblogs.com/alby/archive/2011/03/30/aspdotnet-mvc-update-3.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/alby/archive/2011/03/30/aspdotnet-mvc-update-3.html"/><content type="html">&lt;div&gt;&lt;strong&gt;五、SessionStateAttribute&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;构造SessionStateAttribute对象时必须传入一个SessionStateBehavior枚举值，通过Attribute的Behavior属性可以获取该值。&lt;br /&gt;该Attribute只能用于引用类型(AttributeTargets.Class)，不允许重复使用(AllowMultiple=false),允许继承(Inherited=true)。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;六、MvcRouteHandler&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;MvcRouteHandler类增加了一个接受IControllerFactory接口实现类的对象作为参数传的构造方法，构造对象允许传入null值。而构造方法内部只是简单的将参数赋给一个私有变量_controllerFactory。&lt;br /&gt;&lt;br /&gt;还增加了一个GetSessionStateBehavior虚方法，接受RequestContext型参数，返回一个SessionStateBehavior对象。&lt;br /&gt;在方法内部，创建一个名为controllerFactory的IControllerFactory型局部变量。&lt;br /&gt;如果私有变量_controllerFactory不为null，则赋给controllerFactory,否则通过ControllerBuilder.Current.GetControllerFactory()获取默认的ControllerFactory(注意，并非就一定是DefaultControllerFactory)赋值。然后返回controllerFactory的GetControllerSessionBehavior方法的执行结果。&lt;br /&gt;&lt;br /&gt;GetControllerSessionBehavior方法是IControllerFactory接口新增的。&lt;br /&gt;在DefaultControllerFactory中，GetControllerSessionBehavior是通过反射来获取对应Controller的SessionStateAttribute(会进行缓存)，并返回它的Behavior属性。&lt;br /&gt;&lt;br /&gt;MvcRouteHandler类的GetHttpHandler方法中，会调用GetSessionStateBehavior方法获取一个SessionStateBehavior枚举值,并通过当前请求上下文的SetSessionStateBehavior设置当前请求的SessionState。当然，GetHttpHandler方法返回的是一个new出来的MvcHandler对象。&lt;br /&gt;&lt;br /&gt;从这里我们不难看出MVC3给我们提供的一个新的扩展点：&lt;br /&gt;1、通过接受IControllerFactory接口实现类的对象作为参数传的构造方法创建MvcRouteHandler(RouteCollectionExtensions.MapRoute是通过无参构造方法创建对象)。&lt;br /&gt;2、实现新的IControllerFactory来达到不以默认方式获取Controller对应的SessionStateBehavior(比如通过直接缓存而不是通过反射再缓存)，或者设置某些命名空间下全局的SessionStateBehavior。&lt;br /&gt;3、甚至我们可以实现ActionSessionStateAttribute，设置某个Action的SessionStateBehavior而不是整个Controller。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;七、IControllerActivator和DefaultControllerFactory&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;我们知道，ControllerFactory是为了创建Controller而生，在以上的内容中对此也有所提及。&lt;br /&gt;在MVC3中的DefaultControllerFactory类中，使创建Controller的方式更灵活，并能配合DI(详见DenpendencyResolver相关)。&lt;br /&gt;首先增加了一个带IControllerActivator接口参数的公共构造方法。&lt;br /&gt;IControllerActivator接口的唯一方法Create类似于GetControllerInstance方法。&lt;br /&gt;我们知道MVC2的DefaultControllerFactory类中的GetControllerInstance方法直接使用Activator.CreateInstance类创建对象。&lt;br /&gt;通过MVC3中新增的有参公共构造函数，我们可以很容易的改变这种方式。在MV2中我们如果想改变，得重新实现一个IControllerFactory或继承DefaultControllerFactory类重写GetControllerInstance需方法。&lt;br /&gt;&lt;br /&gt;DefaultControllerFactory还提供了一个internal的带三个参数的构造方法。该方法的实现机制类似于ControllerBuilder,这里就不再重复分析。&lt;br /&gt;可以想象，如果该构造函数是public的，我们就用DefaultControllerFactory就可以灭掉很多之前MVC2中，仅为了创建带有参构造函数Controller类而实现的ControllerFactory。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;八、Filter&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;MVC3新增加了Filter相关的若干类或枚举：&lt;br /&gt;Filter、FilterProviderCollection、FilterProviders、&lt;br /&gt;GlobalFilterCollection、GlobalFilters、&lt;br /&gt;FilterAttributeFilterProvider、ControllerInstanceFilterProvider、&lt;div&gt;FilterScope&lt;/div&gt;&lt;br /&gt;关于Filter的讨论在很久以前就做过：&lt;br /&gt;&lt;a target="_blank" href="http://www.cnblogs.com/alby/archive/2010/12/08/1900555.html"&gt;ASP.Net MVC探索之路 - 不想在多个Action上写同样的FitlerAttribute(上)&lt;/a&gt;&lt;br /&gt;&lt;a target="_blank" href="http://www.cnblogs.com/alby/archive/2010/12/15/1906485.html"&gt;&lt;/a&gt;&lt;a href="http://www.cnblogs.com/alby/archive/2010/12/15/1906485.html"&gt;ASP.Net MVC探索之路 - 不想在多个Action上写同样的FitlerAttribute(下)&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/alby/aggbug/1999729.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/alby/archive/2011/03/30/aspdotnet-mvc-update-3.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/alby/archive/2011/03/25/aspdotnet-mvc-update-2.html</id><title type="text">ASP.NET MVC 3 RTM 更新(2)</title><summary type="text">三、IResolver&lt;TService&gt;和SingleServiceResolver&lt;TService&gt;:IResolver&lt;TService&gt;、MultiServiceResolver&lt;TService&gt;:IResolver&lt;IEnumerable&lt;TService&gt;&gt;IResolver&lt;TService&gt;接口只有一个TService型的Current只读属性,返回相应类型的一个对象。这是一个有Lazy意味的轻量接口。一个简单的IResolver&lt;TService&gt;接口的实现类中，Current</summary><published>2011-03-25T07:16:00Z</published><updated>2011-03-25T07:16:00Z</updated><author><name>alby</name><uri>http://www.cnblogs.com/alby/</uri></author><link rel="alternate" href="http://www.cnblogs.com/alby/archive/2011/03/25/aspdotnet-mvc-update-2.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/alby/archive/2011/03/25/aspdotnet-mvc-update-2.html"/><content type="html">&lt;div&gt;&lt;strong&gt;三、IResolver&amp;lt;TService&amp;gt;和SingleServiceResolver&amp;lt;TService&amp;gt;:IResolver&amp;lt;TService&amp;gt;、MultiServiceResolver&amp;lt;TService&amp;gt;:IResolver&amp;lt;IEnumerable&amp;lt;TService&amp;gt;&amp;gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;IResolver&amp;lt;TService&amp;gt;接口只有一个TService型的Current只读属性,返回相应类型的一个对象。这是一个有Lazy意味的轻量接口。&lt;br /&gt;一个简单的IResolver&amp;lt;TService&amp;gt;接口的实现类中，Current可以返回Activator.CreateInstance创建的实例&amp;#8212;&amp;#8212;在面向接口编程方面讲，完全是有意义的。&lt;br /&gt;&lt;br /&gt;SingleServiceResolver类是IResolver&amp;lt;TService&amp;gt;的实现，它用于获取单个对象，其实现原理是：在构造对象时，方法内部或作为参数指定一种默认的对象创建(获取)"方式"&amp;#8212;&amp;#8212;方式1，作为参数传入另一种创建(获取)"方式"&amp;#8212;&amp;#8212;方式2和当&lt;br /&gt;当两种创建(获取)对象都不成功的情况下(两种方式都成功，则会抛出异常)提供一个默认对象。&lt;br /&gt;&lt;br /&gt;具体来说，在它公共的构造方法中，指定的方式1为DependencyResolver.Current(IDependencyResolver)。&lt;br /&gt;当调用SingleServiceResolver类的Current属性时，首先判断如果方式1不为null，则通过DependencyResolver.Current.GetService(typeof(TService))获取一个TService对象，如果创建(获取)成功，则尝试方式2创建(获取)，如果也成功则抛出异常。&lt;br /&gt;返回值的时候，先判方式1如果为null,则获取方式2的执行结果，如果结果不为null，则返回该结果，否则返回默认对象。&lt;br /&gt;&lt;br /&gt;在它的internal构造方法中，还允许传入默认创建(获取)方式以赋给方式1。在两个构造方法中还允许传入一个字符串标明是哪个方法在创建SingleServiceResolver对象(或者说Current返回的对象)。在有异常发生时，可以将该字符串传入异常对象。&lt;br /&gt;&lt;br /&gt;MultiServiceResolver类也是IResolver&amp;lt;TService&amp;gt;的实现，它用于获取一个集合对象，其实现原理是：在构造对象时，方法内部或作为参数指定一种默认的对象创建(获取)"方式"&amp;#8212;&amp;#8212;方式1，作为参数传入另一种创建(获取)"方式"&amp;#8212;&amp;#8212;方式2。&lt;br /&gt;返回两种方式创建(获取)的集合的合集。&lt;br /&gt;&lt;br /&gt;具体来说，在它公共的构造方法中，指定的方式1为DependencyResolver.Current(IDependencyResolver)。&lt;br /&gt;当调用MultiServiceResolver类的Current属性时，首先判断如果方式1不为null，则通过DependencyResolver.Current.GetServices(typeof(TService))获取一个IEnumerable&amp;lt;TService&amp;gt;对象，该集合对象可以没有元素但不能为null，&lt;br /&gt;然后将方式2创建的集合与方式1创建(获取)的集合合并返回。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;四、ControllerBuilder&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;我们知道在MVC2中，Controller通过ControllerFactory创建，而ControllerFactory通过ControllerBuilder的单例ControllerBuilder.Current的GetControllerFactory()方法获取。类的默认构造方法中会初始化一个DefaultControllerFactory对象，并通过SetControllerFactory方法将其包装成一个Func&amp;lt;IControllerFactory&amp;gt;实例，并赋值给_factoryThunk私有委托，当调用GetControllerFactory方法时，返回的是该委托的执行结果。&lt;br /&gt;&lt;br /&gt;在MVC3中，ControllerBuilder类的构造方法和GetControllerFactory方法的实现又有所不同。&lt;br /&gt;ControllerBuilder有一个IResolver&amp;lt;IControllerFactory&amp;gt;型的私有变量_serviceResolver。从上面的分析我们知道，IResolver&amp;lt;IControllerFactory&amp;gt;有唯一的只读属性T Current，调用_serviceResolver.Current将返回一个IControllerFactory对象。&lt;br /&gt;默认构造不再直接创建DefaultControllerFactory对象，只是简单的调用新增的接受一个IResolver&amp;lt;IControllerFactory&amp;gt;接口参数的构造方法。该方法目前是internal的。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal ControllerBuilder(IResolver&amp;lt;IControllerFactory&amp;gt; serviceResolver) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _serviceResolver = serviceResolver ?? new SingleServiceResolver&amp;lt;IControllerFactory&amp;gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; () =&amp;gt; _factoryThunk(),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new DefaultControllerFactory { ControllerBuilder = this },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "ControllerBuilder.GetControllerFactory"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;在有参构造方法内部，如果传入的参数serviceResolver为null则创建一个实现了IResolver&amp;lt;IControllerFactory&amp;gt;接口的SingleServiceResolver&amp;lt;TService&amp;gt;类的对象赋给私有变量_serviceResolver。ControllerBuilder.Current是一个通过默认构造函数创建的对象，用到了单例模式。所以这里serviceResolver参数是为null的。&lt;br /&gt;&lt;br /&gt;深入SingleServiceResolver类内部我们知道，它首先会尝试从DependencyResolver.Current.GetService(typeof(IControllerFactory))获取IControllerFactory对象，在默认情况会调用Activator.CreateInstance(typeof(IControllerFactory)),当然会是null。所以最终会创建DefaultControllerFactory作为我们的默认ControllerFactory。&lt;br /&gt;&lt;br /&gt;假设定义了一个UnityControllerFactory:IControllerFactory。&lt;br /&gt;首先，我们可以像MVC2中那样使用SetControllerFactory设置IControllerFactory&lt;br /&gt;假设我们又实现了一个UnityDependencyResolver:IDenpendencyResovler,并将其设置为当前的IDenpendencyResovler。&lt;br /&gt;在UnityContainer中将UnityControllerFactory映射到IControllerFactory接口,同样可以达到设置ControllerFactory的目的。&lt;br /&gt;&lt;br /&gt;另外，GetControllerFactory方法返回的不再是像MVC2中的_factoryThunk的执行结果，而是_serviceResolver的Current属性。&lt;/div&gt;&lt;img src="http://www.cnblogs.com/alby/aggbug/1995501.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/alby/archive/2011/03/25/aspdotnet-mvc-update-2.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/alby/archive/2011/03/25/aspdotnet-mvc-update-1.html</id><title type="text">ASP.NET MVC 3 RTM 更新(1)</title><summary type="text">一、路由(Routing)路由功能最初整合在ASP.NET MVC(以下简称MVC)中，后来被独立出来形成了System.Web.Routing 3.5程序集。ASP.NET 4已经把Routing功能已经转移到了System.Web 4 程序集下作为基础服务的一部分。在使用Routing功能时，您已不再需要在web.config中注册Module，因为UrlRoutingModule已经集成进ASP.NET 4中了，就像FormsAuthenticationModule等Module一样(C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config</summary><published>2011-03-25T05:23:00Z</published><updated>2011-03-25T05:23:00Z</updated><author><name>alby</name><uri>http://www.cnblogs.com/alby/</uri></author><link rel="alternate" href="http://www.cnblogs.com/alby/archive/2011/03/25/aspdotnet-mvc-update-1.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/alby/archive/2011/03/25/aspdotnet-mvc-update-1.html"/><content type="html">&lt;div&gt;&lt;strong&gt;一、路由(Routing)&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;路由功能最初整合在ASP.NET MVC(以下简称MVC)中，后来被独立出来形成了System.Web.Routing 3.5程序集。ASP.NET 4已经把Routing功能已经转移到了System.Web 4 程序集下作为基础服务的一部分。在使用Routing功能时，您已不再需要在web.config中注册Module，因为UrlRoutingModule已经集成进ASP.NET 4中了，就像FormsAuthenticationModule等Module一样(&lt;div&gt;C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\web.config 的httpModules节点)。而ASP.NET MVC 3(以下简称MVC3)是基于ASP.NET 4的。&lt;/div&gt;&lt;br /&gt;在System.Web.Routing 3.5中，UrlRoutingModule通过处理PostResolveRequestCache和PostMapRequestHandler事件来配合设置请求处理程序(IHttpHandler)，而在System.Web.Routing 4中，只处理了PostResolveRequestCache事件(PostMapRequestHandler事件也处理了，但什么都不做，但已标明过期)。&lt;br /&gt;&lt;br /&gt;值得一提的是ASP.NET 4的HttpRequest新增加了一个RequestContext属性，其类型正是System.Web.Routing.RequestContext。该类封装了当前请求上下文以及RouteData。&lt;br /&gt;&lt;br /&gt;增加了PageRouteHandler类以支持WebForm的路由功能,该类实现IRouteHandler接口。而在ASP.NET 2.0中，得自己实现类似的IRouteHandler。&lt;br /&gt;为了更方便的添加该类型的路由规则，RouteCollection类中还新增加了四个MapPageRoute的重载方法。&lt;br /&gt;&lt;br /&gt;简单演示一下：&lt;br /&gt;1、新建一个基于.Net 4的Web Application。&lt;br /&gt;2、新建Global.asa并修改Global.asa.cs的Application_Start方法&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; void Application_Start(object sender, EventArgs e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 以下两种方式都可以添加路由规则，显然MapPageRoute更方便、清晰一些&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //RouteTable.Routes.Add("newRoute",new Route("TestRouting",new PageRouteHandler("~/TestRouting.aspx")));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RouteTable.Routes.MapPageRoute("newRoute"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; , "RoutingTest"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; , "~/RoutingTest.aspx");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;3、新建Web窗体，命名为RoutingTest.aspx。在里面随便输入一些内容。&lt;br /&gt;4、启动调试(F5),输入类似的网址：http://localhost:3232/RoutingTest&lt;br /&gt;&lt;br /&gt;一切正常的话应该显示出您输入的内容。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;二、IDependencyResolver和DependencyResolver&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Ioc/DI(Inversion of Control / the Dependency Injection,控制反转/依赖注入)是实现系统解耦的一大利器。.Net平台可用的DI容器有Castle Windsor、StructureMap、Autofac 、Unity等。在MVC2中我们就可以很容易的使用这些容器，MVC3在DI方面又为我们做了什么呢？&lt;br /&gt;&lt;br /&gt;需要清楚一点，MVC3对DI的支持并不是说它内置了类似于Autofac之类的DI容器。它只是内置了一种创建(获取)对象的默认&amp;#8220;方式&amp;#8221;(DefaultDependencyResolver)，这种&amp;#8220;方式&amp;#8221;内部其中一个途径是通过Activator.CreateInstance(Type serviceType)来创建对象。更重要的是，它提供了一种API让我们可以改变这种方式。这使得我们可以使用Autofac之类的DI方式来替换。&lt;br /&gt;&lt;br /&gt;下面我们从源码角度分析一下MVC3是如何实现这种机制的。&lt;br /&gt;&lt;br /&gt;首先看看IDependencyResolver接口，该接口正是上面所说的创建(获取)对象的&amp;#8220;方式&amp;#8221;。接口有两个方法，GetService根据Type获取一个简单对象，GetServices根据Type获取一个集合对象。&lt;br /&gt;public interface IDependencyResolver&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; object GetService(Type serviceType);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;object&amp;gt; GetServices(Type serviceType);&lt;br /&gt;}&lt;br /&gt;DependencyResolver并不是IDependencyResolver接口的实现。&lt;br /&gt;它有两个私有内联类DefaultDependencyResolver和DelegateBasedDependencyResolver，都是现实的IDependencyResolver接口；&lt;br /&gt;一个DependencyResover型的私有变量_instance；&lt;br /&gt;一个IDependencyResolver型的私有变量_current；&lt;br /&gt;一个静态构造方法，方法内部创建一个DependencyResolver赋给_instance变量；&lt;br /&gt;一个默认构造方法，方法内部创建一个DefaultDependencyResolver赋给_current变量；&lt;br /&gt;两个只读的类型为IDependencyResolver的属性Current和InnerCurrent,这两个属性的get方法最终返回的是_instance变量&amp;#8212;&amp;#8212;典型的单例模式；&lt;br /&gt;三个InnerSetResolver重载方法和三个SetResolver重载方法。每个SetResolver只是简单的调用对应的InnerSetResolver方法。这些方法用于设置当前的IDependencyResolver对象，并将对象赋给_current变量。&lt;br /&gt;&lt;br /&gt;当我们需要根据某种类型比如SomeClass创建相应的对象时，我们这样调用：DependencyResolver.Current.GetService(typeof(SomeType))。&lt;br /&gt;当然，返回结合对象就这样调用DependencyResolver.Current.GetServices(typeof(SomeType))。&lt;br /&gt;默认情况下我们使用的是DefaultDependencyResolver对象，在该对象的GetService方法内部，通过调用Activator.CreateInstance(typeof(SomeType))来创建对象，而GetServices方法返回的是numerable.Empty&amp;lt;object&amp;gt;()生成的对象。&lt;br /&gt;&lt;br /&gt;IDependencyResolver接口是创建(获取)对象的&amp;#8220;方式&amp;#8221;，而SetResolver方法等则是改变这种方式的API。下面简单分析一下这几个方法。&lt;br /&gt;1、InnerSetResolver(IDependencyResolver resolver)&lt;br /&gt;该方法接受一个IDependencyResolver型参数，方法内部直接将值赋给_current变量。&lt;br /&gt;2、InnerSetResolver(Func&amp;lt;Type, object&amp;gt; getService, Func&amp;lt;Type, IEnumerable&amp;lt;object&amp;gt;&amp;gt; getServices)&lt;br /&gt;该方法接受两个委托，第一个接受一个Type型参数返回object型对象，而第二个返回IEnumerable&amp;lt;object&amp;gt;型集合对象。&lt;br /&gt;方法内部创建一个DelegateBasedDependencyResolver对象。调用DelegateBasedDependencyResolver.GetService(Type type)返回的&lt;br /&gt;是getService(type)的执行结果。相应的，调用GetServices(Type type)返回的是getServices(type)的执行结果。&lt;br /&gt;3、InnerSetResolver(object commonServiceLocator)&lt;br /&gt;该方法接受一个object型参数，方法内部会通过反射的方式尝试获取方法名为"GetInstance"和"GetAllInstances"，参数为Type型的两个方法;&lt;br /&gt;接着检查方法的返回值是否分别是object型和IEnumeralbe&amp;lt;object&amp;gt;型，如果是创建一个DelegateBasedDependencyResolver对象，两个方法作为构造方法&lt;br /&gt;参数传入，并将对象赋给_current变量。返回值的不匹配则抛出异常。&lt;br /&gt;&lt;br /&gt;您可能需要CommonServiceLocator的资料：http://commonservicelocator.codeplex.com&lt;br /&gt;&lt;br /&gt;另外，DependencyResolverExtensions类是IDependencyResolver接口的扩展方法，分别是相应方法的泛型实现。&lt;br /&gt;public static class DependencyResolverExtensions&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static TService GetService&amp;lt;TService&amp;gt;(this IDependencyResolver resolver)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (TService) resolver.GetService(typeof(TService));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IEnumerable&amp;lt;TService&amp;gt; GetServices&amp;lt;TService&amp;gt;(this IDependencyResolver resolver)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return resolver.GetServices(typeof(TService)).Cast&amp;lt;TService&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;IDependencyResolver接口的实现类中，通常采用外观模式。内部包含一个DI容器，当调用GetService或GetServices方法时，调用DI容器相应的方法。&lt;/div&gt;&lt;img src="http://www.cnblogs.com/alby/aggbug/1995322.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/alby/archive/2011/03/25/aspdotnet-mvc-update-1.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/alby/archive/2011/03/21/websocket-handshake.html</id><title type="text">WebSocket握手协议</title><summary type="text">1、客户端握手请求（注意：键值之间有一个空格,行间有换行符号0x13x10或者说\r\n）GET /WebSocket/LiveVideo HTTP/1.1Upgrade: WebSocketConnection: UpgradeHost: localhost:8080 (客户端请求主机)Origin: http://127.0.0.1 (来源网页地址)Sec-WebSocket-Key1: 23 asdfJKj,asdjkSec_WebSocket-Key2: wewerw234 jij9980x13x10 + 8个字节Sec_WebSocket-Key3值，没有键名(注意，这里的0x13x</summary><published>2011-03-21T06:19:00Z</published><updated>2011-03-21T06:19:00Z</updated><author><name>alby</name><uri>http://www.cnblogs.com/alby/</uri></author><link rel="alternate" href="http://www.cnblogs.com/alby/archive/2011/03/21/websocket-handshake.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/alby/archive/2011/03/21/websocket-handshake.html"/><content type="html">&lt;div&gt;1、客户端握手请求（注意：键值之间有一个空格,行间有换行符号0x13x10或者说\r\n）&lt;br /&gt;GET /WebSocket/LiveVideo HTTP/1.1&lt;br /&gt;Upgrade: WebSocket&lt;br /&gt;Connection: Upgrade&lt;br /&gt;Host: localhost:8080 &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;(客户端请求主机)&lt;br /&gt;Origin: http://127.0.0.1 &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;(来源网页地址)&lt;br /&gt;Sec-WebSocket-Key1: 23 asdfJKj,asdjk&lt;br /&gt;Sec_WebSocket-Key2: wewerw234 jij998&lt;br /&gt;&lt;div&gt;&lt;div&gt;0x13x10 + 8个字节Sec_WebSocket-Key3值，没有键名(注意，这里的0x13x10的额外的，也就说有两个连续的0x13x10)&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;2、服务端握手回复&lt;br /&gt;HTTP/1.1 101 Web Socket Protocol Handshake&lt;br /&gt;Upgrade: WebSocket&lt;br /&gt;Connection: Upgrade&lt;br /&gt;Sec-WebSocket-Origin: http://127.0.0.1 &amp;nbsp;&amp;nbsp; &amp;nbsp;(来源网页地址)&lt;br /&gt;Sec-WebSocket-Location: ws://localhost:8080/WebSocket/LiveVideo&lt;br /&gt;16个字节的加密KEY&lt;br /&gt;&lt;br /&gt;加密KEY算法：&lt;br /&gt;&lt;br /&gt;Sec_WebSocket-Key1的产生方式：&lt;br /&gt;(1)提取客户端请求的Sec_WebSocket-Key1中的数字符组成字符串k1&lt;br /&gt;(2)转换字符串为8个字节的长整型intKey1&lt;br /&gt;(3)统计客户端请求的Sec_WebSocket-Key1中的空格数k1Spaces&lt;br /&gt;(4)intK1/k1Spaces取整k1FinalNum&lt;br /&gt;(5)将k1FinalNum转换成字节数组再反转最终形成4个字节的Sec_WebSocket-Key1&lt;br /&gt;&lt;br /&gt;Sec_WebSocket-Key2的产生方式：&lt;br /&gt;(1)提取客户端请求的Sec_WebSocket-Key2中的数字符组成字符串k2&lt;br /&gt;(2)转换字符串为8个字节的长整型intKey2&lt;br /&gt;(3)统计客户端请求的Sec_WebSocket-Key2中的空格数k2Spaces&lt;br /&gt;(4)intK2/k2Spaces取整k2FinalNum&lt;br /&gt;(5)将k2FinalNum转换成字节数组再反转最终形成4个字节的Sec_WebSocket-Key2&lt;br /&gt;&lt;br /&gt;Sec_WebSocket-Key3的产生方式：&lt;br /&gt;客户端握手请求的最后8个字节&lt;br /&gt;&lt;br /&gt;将Sec_WebSocket-Key1、Sec_WebSocket-Key2、Sec_WebSocket-Key3合并成一个16字节数组&lt;br /&gt;再进行MD5加密形成最终的16个字节的加密KEY&lt;br /&gt;&lt;br /&gt;3、消息发送接收&lt;br /&gt;客户端和服务端发送非握手文本消息时，消息以utf-8编码，并以0x00开头，0xFF结尾。&lt;/div&gt;&lt;p&gt;&lt;br /&gt;备注：本协议到期时间：2011-2-17&lt;br /&gt;&lt;br /&gt;参考资料：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;http://www.whatwg.org/specs/web-socket-protocol/&lt;br /&gt;&lt;div&gt;http://superwebsocket.codeplex.com/&lt;/div&gt;&lt;/div&gt;&amp;nbsp;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/alby/aggbug/1990214.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/alby/archive/2011/03/21/websocket-handshake.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/alby/archive/2011/01/26/how-to-rebuild-system-databases-in-sql-server-2008.html</id><title type="text">MS SQL Server 2008 master数据库损坏故障解决</title><summary type="text">本地电脑上安装的MS SQL Server 2008 R2可能因为硬盘原因，导致SQL Server服务无法启动，在事件查看器中看到若干错误和信息，其中有两条提示可能master损坏：1、错误：传递给数据库 'master' 中的日志扫描操作的日志扫描号 (184:416:1) 无效。此错误可能指示数据损坏，或者日志文件(.ldf)与数据文件(.mdf)不匹配。如果此错误是在复制期间出现的，请重新创建发布。否则，如果该问题导致启动期间出错，请从备份还原。2、信息：无法恢复 master 数据库。SQL Server 无法运行。请利用完整备份还原 master 数据库，修复它，或者重新生成它。有</summary><published>2011-01-26T06:36:00Z</published><updated>2011-01-26T06:36:00Z</updated><author><name>alby</name><uri>http://www.cnblogs.com/alby/</uri></author><link rel="alternate" href="http://www.cnblogs.com/alby/archive/2011/01/26/how-to-rebuild-system-databases-in-sql-server-2008.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/alby/archive/2011/01/26/how-to-rebuild-system-databases-in-sql-server-2008.html"/><content type="html">&lt;div&gt;本地电脑上安装的MS SQL Server 2008 R2可能因为硬盘原因，导致SQL Server服务无法启动，在事件查看器中看到若干错误和信息，其中有两条提示可能master损坏：&lt;br /&gt;1、错误：传递给数据库 'master' 中的日志扫描操作的日志扫描号 (184:416:1) 无效。此错误可能指示数据损坏，或者日志文件(.ldf)与数据文件(.mdf)不匹配。如果此错误是在复制期间出现的，请重新创建发布。否则，如果该问题导致启动期间出错，请从备份还原。&lt;br /&gt;2、信息：无法恢复 master 数据库。SQL Server 无法运行。请利用完整备份还原 master 数据库，修复它，或者重新生成它。有关如何重新生成 master 数据库的详细信息，请参阅 SQL Server 联机丛书。&lt;br /&gt;&lt;br /&gt;重新安装SQL Server问题不难解决，但太耗时。google到一个快捷的恢复方法，分享如下：&lt;br /&gt;&lt;br /&gt;1、复制model.mdf、mastlog.ldf、model.mdf、modellog.ldf、msdbdata.mdf、msdblog.ldf文件。&lt;br /&gt;从&lt;br /&gt;X:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Binn\Templates&lt;br /&gt;至&lt;br /&gt;X:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA&lt;br /&gt;注：以上&amp;#8220;X:\Program Files\Microsoft SQL Server&amp;#8221;为SQL Server的安装目录。以下的&amp;#8220;C:\Program Files\Microsoft SQL Server&amp;#8221;为系统盘下的目录&lt;br /&gt;&lt;br /&gt;2、定位并执行安装命令&lt;br /&gt;&lt;br /&gt;首先找到安装命令：&lt;br /&gt;C:\Program Files\Microsoft SQL Server\100\Setup Bootstrap\Release\setup.exe&lt;br /&gt;&lt;br /&gt;如果只是Windows身份验证模式，只需要如下语法即可：&lt;br /&gt;setup /ACTION=REBUILDDATABASE /QUIET /INSTANCENAME=&amp;lt;instance name&amp;gt; /SQLSYSADMINACCOUNTS=&amp;lt;accounts&amp;gt; &lt;br /&gt;如果是复合身份验证模式，则需要使用/SAPWD参数提供sa的密码：&lt;br /&gt;setup /ACTION=REBUILDDATABASE /QUIET /INSTANCENAME=&amp;lt;instance name&amp;gt; /SQLSYSADMINACCOUNTS=&amp;lt;accounts&amp;gt; /SAPWD=&amp;lt;sa password&amp;gt;&lt;br /&gt;&lt;br /&gt;我安装时设置的是复合认证模式，SQL Server系统管理员帐号是administrators组，sa密码是123456。并且就一个默认实例：MSSQLSERVER。&lt;br /&gt;所以在命令行执行如下命令：&lt;br /&gt;setup /ACTION=REBUILDDATABASE /QUIET /INSTANCENAME=MSSQLSERVER /SQLSYSADMINACCOUNTS=administrators /SAPWD=123456&lt;br /&gt;&lt;br /&gt;执行完毕后没有任何提示信息（不管成功与否），但是可以马上在C:\Program Files\Microsoft SQL Server\100\Setup Bootstrap\Log\Summary.txt中查看安装日志。&lt;br /&gt;&lt;br /&gt;最后，在Sql Server Configuration Manager中启动SQL Server服务成功。&lt;br /&gt;&lt;br /&gt;参考资料：&lt;br /&gt;http://blogs.msdn.com/b/psssql/archive/2008/08/29/how-to-rebuild-system-databases-in-sql-server-2008.aspx&lt;/div&gt;&lt;img src="http://www.cnblogs.com/alby/aggbug/1945472.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/alby/archive/2011/01/26/how-to-rebuild-system-databases-in-sql-server-2008.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/alby/archive/2010/12/15/1906485.html</id><title type="text">ASP.Net MVC探索之路 - 不想在多个Action上写同样的FitlerAttribute(下)</title><summary type="text">ASP.NET MVC 3.0 RC相较于2.0 RTM增加了10个左右的接口、类或枚举来增强Filter，并且为ControllerActionInvoker增加了2个构造函数来配合这一切。目前白皮书上只有寥寥几句提到这方面而已。</summary><published>2010-12-15T03:41:00Z</published><updated>2010-12-15T03:41:00Z</updated><author><name>alby</name><uri>http://www.cnblogs.com/alby/</uri></author><link rel="alternate" href="http://www.cnblogs.com/alby/archive/2010/12/15/1906485.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/alby/archive/2010/12/15/1906485.html"/><content type="html">&lt;div&gt;距离&lt;a href="http://www.cnblogs.com/alby/archive/2010/12/08/1900555.html"&gt;上一篇&lt;/a&gt;的分析已经好几天。一是由于关注的人比较少，二是正在移植入ASP.NET MVC 3.0 RC，所以就没急着做出来。&lt;br /&gt;今天花了点时间把Demo做出来提供给大家下载，希望大家能够提点意见。&lt;br /&gt;&lt;br /&gt;我们知道，在ASP.NET MVC 3.0中为我们提供了一个GlobalFilters(包含一个GlobalFilterCollection)用于注册全局Filter，但它也不够灵活&amp;#8212;&amp;#8212;其实也不能这么说，因为它的目的本来就只是要提供一个全局的Filter注册器。包括GlobalFilters在内，ASP.NET MVC 3.0 RC相较于2.0 RTM增加了10个左右的接口、类或枚举来增强Filter，并且为ControllerActionInvoker增加了2个构造函数来配合这一切。特别是新增加的FilterAttributeFilterProvider、GlobalFilterCollection这两个IFilterProvider，使Filter可以进行缓存，相对于ASP.NET MVC 2.0，性能上有所提升。目前白皮书上只有寥寥几句稍微提到这方面而已。&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;在今天的Demo中，我实现了一个FilterRegistryFilterProvider:IFilterProvider，它与GlobalFilters比较的优点在于提供了一种可扩展、可配置的Filter注入方式：&lt;br /&gt;&lt;br /&gt;1、摒弃在Controller和Action上标记Attribute的方式实现Filter注入的方式，在需要时通过反射来来获取，虽然我对反射并无恶感，既然能提高那么一点点性能，又何乐而不为呢。而且将Filter在Controller外部注入，也去除了与Controller的耦合性。就正如GlobalFilters一样，不需要使用Attribute标记的方式来注入。&lt;br /&gt;2、如果有AController、BController、CDEFG...等，可以指定只在某些Controller注入Filter，需求改变时，可以方便取消注入。正如第一条所说，这一切都不用改动我们已经编译好的Controllers。&lt;br /&gt;3、如果AController的ActionA和BController的ActionC需要某个Filter，可以精确注入。&lt;br /&gt;4、可以让某个或某些Route下的Action注入&lt;br /&gt;5、可以让某个RouteValue等于（不等于、包含）某个值的请求注入Filter。&lt;br /&gt;&lt;div&gt;6、可以让某个DataToken等于（不等于、包含）某个值的请求注入Filter（比如可以给某些area注入）。&lt;/div&gt;7、多个条件组合起来判断，满足高级需求。&lt;br /&gt;8、在系统初始化时，可以像GlobalFilters那样对Filter实例进行缓存，避免不必要的重复创建销毁过程（感谢&lt;a id="Comments1_CommentList_ctl00_NameLink" href="http://www.cnblogs.com/ldp615/" target="_blank"&gt;鹤冲天&lt;/a&gt;提醒）&lt;br /&gt;9、您可以很容易的继续扩展注入的条件。&lt;br /&gt;&lt;br /&gt;话不多说了，上Demo。另，Demo需要ASP.NET MVC 3.0 RC或更高版本、.Net Framework 4。&lt;/div&gt;下载地址：&lt;a href="http://files.cnblogs.com/alby/FilterRegistryDemo.rar" title="FilterRegistryDemo"&gt;FilterRegistryDemo&lt;/a&gt;&lt;img src="http://www.cnblogs.com/alby/aggbug/1906485.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/alby/archive/2010/12/15/1906485.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/alby/archive/2010/12/10/stringlengthrangeattribute.html</id><title type="text">ASP.Net MVC探索之路 - 增加字符串长度范围校验Attribute</title><summary type="text">DataAnnotations提供了RequiredAttribute进行null或Empty校验、StringLengthAttribute进行字符串长度校验，很奇怪怎么不提供一个StringLengthRangeAttribute校验。比如我们在校验输入时，可能需要密码在6-20这个范围内，这时候我们自己扩展一个ValidationAttribute就行了，很简单：[代码]使用举例：[代码]后记：.Net 4下，System.ComponentModel.DataAnnotations命名空间下的StringLengthAttribute增加了MinimumLength属性可供设置最小字符</summary><published>2010-12-10T07:03:00Z</published><updated>2010-12-10T07:03:00Z</updated><author><name>alby</name><uri>http://www.cnblogs.com/alby/</uri></author><link rel="alternate" href="http://www.cnblogs.com/alby/archive/2010/12/10/stringlengthrangeattribute.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/alby/archive/2010/12/10/stringlengthrangeattribute.html"/><content type="html">&lt;div&gt;DataAnnotations提供了RequiredAttribute进行null或Empty校验、StringLengthAttribute进行字符串长度校验，很奇怪怎么不提供一个StringLengthRangeAttribute校验。比如我们在校验输入时，可能需要密码在6-20这个范围内，这时候我们自己扩展一个ValidationAttribute就行了，很简单：&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;!--&lt;br/&gt;&lt;br/&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/&gt;http://www.CodeHighlighter.com/&lt;br/&gt;&lt;br/&gt;--&gt;&lt;span style="color: #000000;"&gt;[AttributeUsage(AttributeTargets.Field&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;|&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;AttributeTargets.Property&lt;br /&gt;,&amp;nbsp;AllowMultiple&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;Inherited&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;StringLengthRangeAttribute&amp;nbsp;:&amp;nbsp;ValidationAttribute&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;_defaultErrorMessage&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;'{0}'&amp;nbsp;长度请保持在&amp;nbsp;{1}-{2}&amp;nbsp;个字符之间&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;StringLengthRangeAttribute(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;minLength,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;maxLength)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;base&lt;/span&gt;&lt;span style="color: #000000;"&gt;(_defaultErrorMessage)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(minLength&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ArgumentOutOfRangeException(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;minLength&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;minLength&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;字符串最小长度不能小于0&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(maxLength&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ArgumentOutOfRangeException(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;maxLength&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;maxLength&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;字符串最大长度不能小于0&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(maxLength&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;minLength)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ArgumentOutOfRangeException(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;maxLength&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;maxLength&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;字符串最大长度必须大于最小长度&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MinLength&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;minLength;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MaxLength&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;maxLength;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;override&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IsValid(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;value)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;valueAsString&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;value&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;as&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(String.IsNullOrEmpty(valueAsString))&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;valueAsString.Length&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;MinLength&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;valueAsString.Length&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;MaxLength;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;override&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;FormatErrorMessage(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;name)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;String.Format(CultureInfo.CurrentUICulture,&amp;nbsp;ErrorMessageString,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name,&amp;nbsp;MinLength,&amp;nbsp;MaxLength);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;MaxLength&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;MinLength&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;使用举例：&lt;br /&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;!--&lt;br/&gt;&lt;br/&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/&gt;http://www.CodeHighlighter.com/&lt;br/&gt;&lt;br/&gt;--&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;UserInputEdit&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[StringLengthRange(&lt;/span&gt;&lt;span style="color: #800080;"&gt;6&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;20&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;ErrorMessage&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;登录密码请保持在6-20个字符之间&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[DisplayName(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;登录密码&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Password&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;后记：.Net 4下，System.ComponentModel.DataAnnotations命名空间下的StringLengthAttribute增加了MinimumLength属性可供设置最小字符串长度。&lt;br /&gt;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/alby/aggbug/1902303.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/alby/archive/2010/12/10/stringlengthrangeattribute.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/alby/archive/2010/12/10/compareattribute-in-asp-net-mvc.html</id><title type="text">ASP.Net MVC探索之路 - Model的比较验证</title><summary type="text">基于ASP.NET MVC 2.0的比较验证</summary><published>2010-12-10T06:00:00Z</published><updated>2010-12-10T06:00:00Z</updated><author><name>alby</name><uri>http://www.cnblogs.com/alby/</uri></author><link rel="alternate" href="http://www.cnblogs.com/alby/archive/2010/12/10/compareattribute-in-asp-net-mvc.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/alby/archive/2010/12/10/compareattribute-in-asp-net-mvc.html"/><content type="html">WebForm有一个比较验证服务器控件CompareValidator ，可以比较两个控件的值大小或一个控件与某一个具体值的大小。可以进行string,int,double,DateTime,decimal这些数据类型的==、!=、&amp;gt;、&amp;lt;、&amp;gt;=、&amp;lt;=比较。在ASP.NET MVC 2.0中，我们已经可以使用基于DataAnnotations的校验方式，对Model的值进行空校验(Required)、范围校验(Range)、字符串长度校验(StringLengthAttribute)等。在ASP.NET MVC 3中，我们还可以使用CompareAttribute进行简单的相等(==)校验，但仅此而已，其他校验就没有了。&lt;br /&gt;&lt;p&gt;&lt;br /&gt;这里我们定义一个类似WebForms验证服务器控件CompareValidator的Attribule。&lt;br /&gt;&lt;br /&gt;首先定义一个枚举表示我们要比较的数据类型：&lt;br /&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;!--&lt;br/&gt;&lt;br/&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/&gt;http://www.CodeHighlighter.com/&lt;br/&gt;&lt;br/&gt;--&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;enum&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationDataType&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;byte&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;String,Integer,Double,Date,Currency&lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;Decimal&lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;再定义一个枚举表示比较方式：&lt;br /&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;!--&lt;br/&gt;&lt;br/&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/&gt;http://www.CodeHighlighter.com/&lt;br/&gt;&lt;br/&gt;--&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;enum&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationCompareOperator&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;byte&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Equal,&amp;nbsp;NotEqual,GreaterThan,GreaterThanEqual,LessThan,LessThanEqual&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;然后当然就是主角CompareAttribute:&lt;br /&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;!--&lt;br/&gt;&lt;br/&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/&gt;http://www.CodeHighlighter.com/&lt;br/&gt;&lt;br/&gt;--&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[AttributeUsage(AttributeTargets.Class,&amp;nbsp;AllowMultiple&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;Inherited&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;CompareAttribute&amp;nbsp;:&amp;nbsp;ValidationAttribute&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;SourceProperty&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;OriginalProperty&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationCompareOperator&amp;nbsp;Operator&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationDataType&amp;nbsp;Type{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;_defaultErrorMessage&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;'{0}'&amp;nbsp;与&amp;nbsp;'{1}'&amp;nbsp;进行&amp;nbsp;{2}&amp;nbsp;比较失败&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;CompareAttribute(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;sourceProperty,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;originalProperty&lt;br /&gt;,&amp;nbsp;ValidationCompareOperator&amp;nbsp;op,&amp;nbsp;ValidationDataType&amp;nbsp;type)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;base&lt;/span&gt;&lt;span style="color: #000000;"&gt;(_defaultErrorMessage)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SourceProperty&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;sourceProperty;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;OriginalProperty&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;originalProperty;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Operator&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;op;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Type&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;type;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;override&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;FormatErrorMessage(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;name)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;String.Format(CultureInfo.CurrentUICulture,&amp;nbsp;ErrorMessageString,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SourceProperty,&amp;nbsp;OriginalProperty,&amp;nbsp;Operator.ToString());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;override&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IsValid(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;value)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PropertyDescriptorCollection&amp;nbsp;properties&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;TypeDescriptor.GetProperties(value);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;sourceProperty&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;properties.Find(SourceProperty,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;ignoreCase&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;.GetValue(value);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;originalProperty&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;properties.Find(OriginalProperty,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;ignoreCase&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;.GetValue(value);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;compare(sourceProperty,originalProperty);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;compare(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;sourceProperty,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;originalProperty)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;switch&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.Type)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationDataType.String:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;.Compare((&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;)sourceProperty&lt;br /&gt;,&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;)originalProperty,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;CultureInfo.CurrentCulture);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationDataType.Integer:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;((&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;)sourceProperty).CompareTo(originalProperty);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationDataType.Double:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;((&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;double&lt;/span&gt;&lt;span style="color: #000000;"&gt;)sourceProperty).CompareTo(originalProperty);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationDataType.Date:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;((DateTime)sourceProperty).CompareTo(originalProperty);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationDataType.Currency:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;((&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;decimal&lt;/span&gt;&lt;span style="color: #000000;"&gt;)sourceProperty).CompareTo(originalProperty);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;switch&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.Operator)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationCompareOperator.Equal:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationCompareOperator.NotEqual:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationCompareOperator.GreaterThan:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationCompareOperator.GreaterThanEqual:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationCompareOperator.LessThan:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationCompareOperator.LessThanEqual:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;在Model中就可以这样使用了，以下校验两次输入的密码是否一致：&lt;br /&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;!--&lt;br/&gt;&lt;br/&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/&gt;http://www.CodeHighlighter.com/&lt;br/&gt;&lt;br/&gt;--&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Compare(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;PasswordConfirm&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Password&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;ValidationCompareOperator.Equal&lt;br /&gt;,ValidationDataType.String,&amp;nbsp;ErrorMessage&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;请确认两次输入的密码一致&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;UserInputEdit&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[DisplayName(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;登录密码&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Password&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[DisplayName(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;确认密码&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;PasswordConfirm&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;如果果要Model中有两个时间，开始时间和结束时间，要求结束时间必须大于开始时间：&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;!--&lt;br/&gt;&lt;br/&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/&gt;http://www.CodeHighlighter.com/&lt;br/&gt;&lt;br/&gt;--&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Compare(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;TimeEnd&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;TimeStart&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;ValidationCompareOperator.GreaterThan&lt;br /&gt;,&amp;nbsp;ValidationDataType.Date,&amp;nbsp;ErrorMessage&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;结束时间必须大于开始时间&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;UserInputEdit&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[DisplayName(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;开始时间&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;DateTime&lt;/span&gt;&lt;span style="color: #000000;"&gt; TimeStart&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[DisplayName(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;结束时间&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt; DateTime&lt;/span&gt;&lt;span style="color: #000000;"&gt; TimeEnd&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;ASP.NET MVC 3也有一个CompareAttribute，但它只能进行Equals比较。同样的比较两次密码是否一致，以上代码可以写成这样：&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;!--&lt;br/&gt;&lt;br/&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/&gt;http://www.CodeHighlighter.com/&lt;br/&gt;&lt;br/&gt;--&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;UserInputEdit&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[DisplayName(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;登录密码&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Password&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[DisplayName(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;确认密码&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Compare(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Password&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;ErrorMessage&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;请确认两次输入的密码一致&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;PasswordConfirm&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;在我们自定义的CompareAttribute中，必须将Attribute应用于class上。如果您想像ASP.NET MVC 3中，将标记写在属性，很遗憾不行。因为ValidationResult IsValid(...)的方法在.Net 4才有，MVC 3也才有相应的支持。如果您已经在使用.Net 4,也可以像下面一样修改我们自定义的CompareAttribute，但请注意以下代码我没测试过：&lt;br /&gt;&lt;/p&gt;&lt;/div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('d12d4811-e2ba-4e50-acf7-e67a3f16500e')"&gt;&lt;img src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" class="code_img_closed" id="code_img_closed_d12d4811-e2ba-4e50-acf7-e67a3f16500e" alt="" /&gt;&lt;img src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" class="code_img_opened" id="code_img_opened_d12d4811-e2ba-4e50-acf7-e67a3f16500e" onclick="cnblogs_code_hide('d12d4811-e2ba-4e50-acf7-e67a3f16500e',event)" style="display: none;"&gt;&lt;div id="cnblogs_code_open_d12d4811-e2ba-4e50-acf7-e67a3f16500e" class="cnblogs_code_hide"&gt;&lt;div&gt;&lt;!--&lt;br/&gt;&lt;br/&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/&gt;http://www.CodeHighlighter.com/&lt;br/&gt;&lt;br/&gt;--&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[AttributeUsage(AttributeTargets.Property&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;|&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;AttributeTargets.Field&lt;br /&gt;,&amp;nbsp;AllowMultiple&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;CompareAttribute&amp;nbsp;:&amp;nbsp;ValidationAttribute&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;OriginalProperty&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationCompareOperator&amp;nbsp;Operator&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationDataType&amp;nbsp;Type{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;_defaultErrorMessage&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;'{0}'&amp;nbsp;与&amp;nbsp;'{1}'&amp;nbsp;进行&amp;nbsp;{2}&amp;nbsp;比较失败&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;CompareAttribute(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;originalProperty&lt;br /&gt;,&amp;nbsp;ValidationCompareOperator&amp;nbsp;op,&amp;nbsp;ValidationDataType&amp;nbsp;type)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;base&lt;/span&gt;&lt;span style="color: #000000;"&gt;(_defaultErrorMessage)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;OriginalProperty&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;originalProperty;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Operator&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;op;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Type&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;type;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;override&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;FormatErrorMessage(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;name)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;String.Format(CultureInfo.CurrentUICulture,&amp;nbsp;ErrorMessageString,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name,&amp;nbsp;OriginalProperty,&amp;nbsp;Operator.ToString());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;protected&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;override&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationResult&amp;nbsp;IsValid(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;value&lt;br /&gt;,&amp;nbsp;ValidationContext&amp;nbsp;validationContext)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PropertyInfo&amp;nbsp;originalProperty&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;validationContext.ObjectType&lt;br /&gt;.GetProperty(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.OriginalProperty);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;originalValue&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;originalProperty.GetValue(validationContext.ObjectInstance,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;!&lt;/span&gt;&lt;span style="color: #000000;"&gt;compare(value,&amp;nbsp;originalValue))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationResult(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.FormatErrorMessage(validationContext&lt;br /&gt;.DisplayName));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;compare(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;sourceProperty,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;originalProperty)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;switch&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.Type)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationDataType.String:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;.Compare((&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;)sourceProperty&lt;br /&gt;,&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;)originalProperty,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;CultureInfo.CurrentCulture);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationDataType.Integer:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;((&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;)sourceProperty).CompareTo(originalProperty);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationDataType.Double:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;((&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;double&lt;/span&gt;&lt;span style="color: #000000;"&gt;)sourceProperty).CompareTo(originalProperty);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationDataType.Date:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;((DateTime)sourceProperty).CompareTo(originalProperty);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationDataType.Currency:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;((&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;decimal&lt;/span&gt;&lt;span style="color: #000000;"&gt;)sourceProperty).CompareTo(originalProperty);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;switch&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.Operator)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationCompareOperator.Equal:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationCompareOperator.NotEqual:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationCompareOperator.GreaterThan:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationCompareOperator.GreaterThanEqual:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationCompareOperator.LessThan:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ValidationCompareOperator.LessThanEqual:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(num&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/alby/aggbug/1902234.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/alby/archive/2010/12/10/compareattribute-in-asp-net-mvc.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
