当前位置: 首页 > news >正文

临时网站搭建门户网站建设提案

临时网站搭建,门户网站建设提案,青岛网站建设小公司排名,网站涉及敏感视频等该怎么做Maverick.Net介绍 Maverick.Net是Java社区开源MVC Web框架Maverick的.Net版本#xff0c;相关资料可以查看项目主页。不管Maverick.Net的是非好坏#xff0c;了解一下它的思想还是不错的。下面的内容是对Maverick.Net整体做一个简单的介绍#xff0c;以求能够从全局的角度了…    Maverick.Net介绍 Maverick.Net是Java社区开源MVC Web框架Maverick的.Net版本相关资料可以查看项目主页。 不管Maverick.Net的是非好坏了解一下它的思想还是不错的。下面的内容是对Maverick.Net整体做一个简单的介绍以求能够从全局的角度了解Maverick.Net一些相关概念大致如何工作。 另外本人没有使用Maverick.Net开发过项目只是看了它的架构、源码之后有一些想法跟大家分享一下也希望能为想了解Maverick.Net的人提供些参考。 1. 主框架 Maverick.Net处理HttpRequest典型的流程如下图 图一处理请求 Reference:MaverickLite Specification Maverick.Net将每一个HttpRequest映射成Command。很容易看到Command的提交者为用户界面也就是View处理者应当是业务逻辑的控制器也就是Controller。这样Maverick.Net Framework在处理每一个Command时主要是解决下面的问题如何从用户界面View提交的参数生成Model用哪个Controller处理特定的Command以及如何将Model传递给这个ControllerController处理结束之后如何将处理结果呈现给用户对Maverick.Net而言就是根据Controller处理结果选择返回哪个View给用户界面以及如何将Model传递给返回的结果View Maverick.Net通过一个配置文件进行配置典型的Command配置节点如下 这是Maverick.Net项目例子Friendbook中一个提交用户注册的Command配置节点。Dispatcher接收到提交注册的HttpRequest之后得到signupSubmit的Command Name从而可以得到这个Command对象。Command将创建指定的Controller对象Friendbook.Ctl.SignupSubmit.Friendbook并调用Controller进行处理。Controller处理结果应当是注册成功需要转向注册成功之后的View或者是发生错误需要转向重新填写注册资料的View。Maverick.Net Framework规定Controller的返回结果必须是一个View的名字这样Command调用Controller处理之后就知道应该呈现哪个View对象。上图中如果注册成功success将调用namesuccess的View如果注册出错例如两次输入的密码不一致等将调用nameerror的View。namesuccess的View类型为redirect将使用当前的MaverickContext对象聚合了HttpContext、Model等对象重定向到另外一个名称为edit.m的Command对象View的类型等后面再介绍nameerror的View类型为document默认类型不需要写typedocument将直接使用Server.Execute()方法得到View的HTML输出并使用Transform对象将用户注册结果View的HTML输出转换成整体页面的HTML代码返回给客户端Transform的概念后面再介绍。 2. 主要的类、对象 Maverick.Net主要的类或对象如下Dispatcher、Command、Controller、View、Transform、MaverickContext。 2.1 Dispatcher Dispatcher是一个HttpHandler类用于拦截和处理HttpRequestHttpRequest-Command的映射就是通过Dispatcher完成。 典型的情况下Maverick.Net使用.m后缀作为ISAPI扩展映射到Command。这种情况下所有浏览器端提交的HttpRequest请求的都是以.m结束的虚拟文件名被提交给Dispatcher。这个文件在服务器上并不存在Dispatcher接收到类似login.m的请求之后将.m后缀去掉取login作为Command Name获取Command对象处理请求。 Maverick.Net老的版本基本上就是照搬Java版本的Maverick在View的层面上只支持象JSP中Servlet的写法也就是纯粹的ASP方式或者是以ASP方式编写的的aspx页面。ASP.Net环境下ViewState、Postback事件机制、用户控件等这些特性都不能使用这对于ASP.Net环境是一种很大的损失。1.2版本开始Maverick.Net的Controller比较完全的支持aspx的服务器端控件、用户控件等这样就可以使用Maverick.Net框架又基于ASP.Net进行设计和开发。 在使用aspx类型的Controller时Dispatcher的拦截作用被去掉了而是使用ASP.Net默认的HttpHandler页面类继承Maverick.Ctl.Aspx.ControllablePageControllablePage在页面的Render方法中切入Maverick.Net框架的控制。这种情况下Command Name也不再是.m后缀方式而直接变成对应的aspx页面名称例如command nameDefault.aspx。 另外Dispatcher处理请求时负责构造MaverickContext对象使Command、Controller、View、Transform等在各自的处理期间都能够得到相应的上下文信息。 2.2 Command Command的作用类似一个指挥官它根据Maverick.config文件的配置创建Controller对象调用Controller进行处理根据Controller的返回结果选择相应的View对象并执行。 Command可以没有Controller这种情况下对Command的请求实际上就是将特定的View呈现给客户端。在Maverick.Net中这是CommandSingleView。 另外也可以继承ICommand接口实现一些特殊功能或者说自定义的Command例如Maverick.Net框架本身实现了两个特殊的CommandReloadCommand和CurrentConfigCommand。CurrentConfigCommand用于查看当前配置文件的内容这个Command读取Maverick.config配置文件的内容直接输出配置文件中的xml。另外Maverick.Net在第一次处理请求的时候会读取Maverick.config中的内容根据配置创建Command、View、Transform对象并缓存起来后续的请求只是从缓存中取相应的对象。如果在第一次访问之后这些配置有更新这些更新不会立即反映到缓存的对象中。ReloadCommand的作用就是根据当前的Maverick.config配置文件内容重新创建缓存的对象。 2.3 Controller Controller的职责是负责业务逻辑的处理。 在典型的应用中Controller首先通过MaverickContext中的HttpContext对象获取从用户界面也就是View提交过来的参数创建Model对象使用Model完成对请求的业务逻辑处理。Controller不同的处理结果将用来确定选择哪个View。在Controller的处理过程中可能会对Model进行更新或者是有一些参数需要传递给View这些将通过MaverickContext这个上下文信息对象完成。 在aspx类型的Controller中因为Dispatcher的拦截作用被丢弃因此MaverickContext对象的创建也是在Controller中完成的。 2.4 View MVC的概念中View负责将某个特定的Model或者是整个Business Domain Model中某些角度的切片呈现给客户端。Maverick.Net中将View分成多种类型。 DocumentView这是默认的View类型。这类型的View将配置一个文件可能是asp或者aspx或者html等调用Server.Execute()方法得到HTML的输出发送给客户端。 ForwardView这类型的View使用当前的MaverickContext重定向到另外一个Command去执行。如果基于structs的方式做系统分析设计一个业务操作可能会被分解成很多个Command/Action将这些Command/Action组合起来就形成一个新的Command/Action或者就对应到某一个业务操作。forward类型的View是用于对这种形式的支持。 RedirectView这类型的View将直接使用Response.Redirect()方法重定向过去。因此也可以将forward类型的View看作是redirect类型的一个特例。实际上在Maverick.Net项目的示例中就有不少这样的用法。这是因为Dispatcher拦截了HttpRequest类似Response.Redirect(edit.m)的语句执行后仍然会被Dispatcher拦截开始一个新的Command的执行。 TrivialView这类型的ViewMaverick.Net将MaverickContext的Model对象直接进行输出取出内容直接输出。这要求MaverickContext的Model对象是下面几种类型String、System.Text.StringBuilder、System.IO.TextReader、Sytem.Xml.XmlNode。 XmlSerializingView这类型的View将MaverickContext的Model序列化成xml格式后输出。这种View主要用于基于xml的网站方案或者是提供系统接口之用途。 2.5 Transform 在Maverick.Net看来View执行的结果还不是呈现给客户端的最终输出之间必须经由Transform进行相应的转换。 Maverick.Net实现的Transform有DocumentTransform、XsltTransform。从XsltTransform类型更容易理解Maverick.Net的Transform概念。对应于XsltTransformView是一个xml或者是XmlSerializing类型的View为了将这个xml转换成HTML输出需要使用xsl/xslt文件进行转换这就是XsltTransform的工作。 对于DocumentTransform的理解Transform这个单词意义上有点牵强。首先DocumentTransform是针对于asp、aspx、html这种文档类型的View。在我们的映象里这种类型的ViewMaverick.Net使用的是Server.Execute()方法这样已经直接得到HTML代码何必再经过一个DocumentTransform处理 实际上对于一个系统工作页面会被分成不同的区域例如页面的Banner区、菜单/功能列表区、通用工具栏等等。这些不同的区域在后面是由不同的Controller负责处理对应的也是不同的Model。在Command的处理中特定的Command只会使用自己的Controller对象负责对相应的Model进行处理因此也只应当对页面中它所辖区域的显示负责。这样View执行的结果就只是Command所辖区域的更新而并不是整个页面。至于如何将这个区域的更新显示在整个页面中这就是DocumentTransform的工作。 目前Maverick.Net对于DocumentTransform用如下方式进行处理。假如是一个document类型的View对应一个aspx文件。View在执行时使用Server.Execute()方法得到输出的HTML代码。但这个还不是最终发向客户端的完整输出而只是其中的一部分Maverick.Net将这个HTML片断保存在HttpContext.Items[]中。DocumentTransform对象对应的也是一个aspx的页面这个页面应当完成系统页面的整体布局并从HttpContext.Items[]中取出View执行后的HTML输出在适当的位置。这样使用Server.Execute()方法调用DocumentTransform的aspx页面后就是完整的发向客户端的HTML了。 其实Transform是考虑了页面的整体布局一个View只会对某个区域负责的状况但是它并不支持复杂的布局只能说是轻量级吧。复杂的布局通过iFrame等实现或者做些修改后结合Ajax方式进行局部更新。 2.6 MaverickContext 这是一个上下文对象主要负责在Command、Controller、View之间传递信息。它包含HttpContext、Model和一个IDictionary类型的Params属性。 HttpContext对象在创建MaverickContext时由创建者Dispatcher或者ControllablePage提供Model由Controller执行处理时创建Params用于在需要的传递其它的参数。 从MVC的角度来看处理流程如下图 3. 简评 在其它一些介绍Maverick.Net的文章里有看到不少对Maverick.Net对ASP.Net下如何运用MVC概念的讨论看法各不一样。其实对.Net下的开发、架构设计的运用本来都是仁者见仁智者见智的事情只是看大家怎么运用了。下面的这些感想只是针对企业级应用的架构模式方面对基于快速开发的小型项目当然另当别论。 3.1 MVC分离 ASP.Net本身的确就是一种MVC的框架可以说是一个很强大又很好用的MVC框架但是有一些障碍在阻挠着我们。ASP.Net本身的许多特性使得M-V-C之间的概念变得模糊甚至混乱。 看一下这个场景添加一个Web Form用Drag-Drop方式在Form中添加GridView、Connection等数据库组建设置相应的属性例如数据库连接GridView的数据源绑定等。可能就简简单单1、2行代码甚至1行都不需要运行这个Web Form就将数据显示出来了。一切是这么方便和简单给BS开发带来一种革命性的思想。可是基于企业级应用架构层面来看从这样的场景中你能得到什么想到什么 当然对富于经验的人这根本就不是问题所在。随便写一段代码就能很好的体现MVC的思想无所谓使用的哪种语言什么工具。假如现在需要几百个开发者协同完成一个项目情况会怎样ASP.Net本身在架构方面没有太多约束力尽管它是一个很好的MVC框架。而这种情况下又非常的需要在架构上对协作的开发者进行约束、规范否则怎样确保按照架构、设计方案进行开发就是件灾难性的事情。 Maverick.Net在MVC的呈现上是非常清晰的。也许你会发现在你的架构中正是需要引入这样的一种思想。不管是哪个子团队哪一个人使用这一个框架就需要理解它的思想按照它的规范进行开发。 3.2 分析设计思想的转变 MDA 从大的视角来看用户需求与软件系统之间的边界就是UI表现层的东西也就是View。一套系统最终都是通过View向用户或者是通过接口向其它系统呈现出它的全部内容。系统开发是对需求的实现而架构设计则是对需求的抽象。 在小型项目中可以不需要什么方法论。把握了需求之后就着重在表现层的设计与用户确认好之后以这个为目标把系统开发出来就OK了。这是很直接的一种方式也是人的思维模式中比较容易接受的一种方式。在企业级应用的架构中如果在不同程度上以这种方式驱动或多或少的以表现层为主体就会妨碍我们的抽象行为也就是影响到架构的质量。 MDA的思想中强调的是先从需求中提取Business Model然后以Model为主体对业务逻辑进行分析。在框架层面将M-V-C比较清晰的区分开来有利于在分析设计思想方面向MDA方式的转换。 3.3 简单而又强大的框架 忘了是在哪里看到的这样一句话。说它简单因为整个Maverick.Net项目的代码很少用于实现的主要对象也不多它仅仅用一个框架性的协议把MVC之间作分离对Model、View、Controller方面并不做任何过多的扩展、处理。所有关于View的呈现方面、Controller的架构方面等完全交由使用者自行决定。说它强大因为整个框架的可扩展性相当不错。 但并不是说这么好的一个框架拿过来用就是了。说它好可能很大程度上是在指它的思想层面并不能代表它目前的实现就是最好的或者说非常合理的。随便列举几点 a) 有考虑多语言的方案但是没有实现。 b) 它的Controller是基于类的层面配置这个该如何使用 方案1把它的Controller当作Business Facade所以可能需要为每个Command写一个Controller类用这个类去整合与Business Model相对应的各个Business Rule类。这种方案有利于分布式、SOA的运用但是每个Command开发个Controller显得有点繁琐。 方案2把Controller作为完整的Business Logic封装在上下文中使用参数等其它机制将Command关联到Controller的方法层面上。 c) Controller View类型的选择 方案1使用aspx类型的Controller。这种方式的优点在于能够使用ASP.Net的机制包括常规的PostBack事件机制、用户控件等或者整合ASP.Net其它一些东西例如Atlas等可能都会比较方便。但以我个人的观点来看不提倡将*.aspx.cs作为Controller而是纯粹的作为View的一部分。*.aspx.cs只负责利用ASP.Net的机制从页面获取参数、创建Model对象传递给控制类在从控制类重新得到Model等相关信息之后Controller处理完毕的结果再利用ASP.Net机制将这些信息进行呈现。 当然将*.aspx.cs作为轻量级的Business Facade也是可以考虑的方案。 方案2使用xml或者Maverick.Net标准的document方式。 其实这两种方式之间的差别还是很大的。使用xml方式的话将使用XsltTransform进行转换可能需要编写大量的xslt文件。使用Maverick.Net标准的document方式是指完全类似ASP的方式了使用DocumentTransform进行转换。这两种方式都是使用Maverick.Net的典型工作方式即以.m作为请求页面的后缀由Dispatcher对HttpRequest进行处理。在页面编写时它们都不能使用ASP.Net特性了说这种方式下完全抛弃了ASP.Net机制也不过分。所以对于ASP.Net开发者将它们视为同一种方式也不奇怪了。 直接使用这种方式开发可能没有多少人能够接受。但是基于这种方式在View的开发方面下一些功夫例如封装、通用化模板的扩展、添加适用于Maverick.Net的Ajax方案等是能够在一定程度上降低这种方式下View开发的繁琐性达到基本可以接受的程度相对于ASP.Net开发者而言。    2006-09-11补充一副图 Maverick.Net代码解析 相关概念、总体处理流程参考Maverick.Net介绍篇不再罗嗦。一看就懂的地方略侧重在貌似疑难之处及部分过程的分析。本人水平一般如有不正确的地方欢迎指正。 Dispatcher 职责一HttpHandler处理Http请求包括Http Request-Command的映射、Command对象的管理二负责对初始化操作的管理。 ExtractCommandName(HttpContext context) 将类似welcome.m的虚拟请求文件名的.m后缀去掉取welcome作为Command的名称。这个名称与maverick.config配置中command节点的name属性相对应。 LoadConfigDocument(HttpContext context) 初始化操作函数之一读取maverick.config配置文件返回XmlDocument对象。 其中有一个转换处理读取maverick.config的xml之后使用一个xsl文件进行转换返回转换之后的XmlDocument对象。可以这样来理解Maverick.Net已经确定了配置文件maverick.config的格式但你可能不是使用这个格式例如你对Maverick.Net做了扩展可能也会相应的调整maverick.config格式等等情况之下你可以用一个xsl将maverick.config配置转换成Maverick.Net要求的格式。 ReloadConfig(HttpContext context) 初始化操作函数之一。 a) 创建Loader对象。Loader创建过程中将创建Command Factory、View Factory、Transform Factory这一系列工厂并利用这些工厂根据maverick.config的配置创建所有的Command、View、Transform对象。 b) 对forward类型View的检查。Maverick.Net介绍篇中提到过forward类型的View是重定向到另外一个Command。这段检查代码就是遍历所有Command下面的View确保forward类型的View重定向的目标Command是存在的。 c) 创建两个特殊的Command并添加到Command集合中。关于这两个特殊Command的说明参考Maverick.Net介绍篇。 Init() 初始化操作的入口函数。    Maverick.Net将Dispatcher的IsReusable属性返回true因此IIS将使用Application Pool重用这个HttpHandler参考HttpHandler相关文档。但注意重用并不是说Init()函数对整个应用而言只会执行一次IIS在并发处理多个Http Request时会为每个请求分配一个Http Handler对象Dispather每一个Dispather实例将执行一次Init()操作。 ProcessRequest(HttpContext context) IHttpHandler接口方法参考MSDN文档。 创建MaverickContext对象时先尝试从HttpContext.Items中获取是因为如果将多个Commands配置成一个链Chain来处理某个Http Request就是Action Flow的概念不过Maverick.Net是在前端控制器Front Controller上实现这个直觉上看跟View的关系太紧密有远离Business Logical/Workflow的感觉但确实是一个Action Flow需要使用同一个MaverickContext对象用于Chain中的各个Command之间协作时传递Model等数据消息。这个Chain中的第一个Command会把MaverickContext对象放入HttpContext.Items中随后的Command都是从HttpContext.Items中获取。Chain中的Command如何传递数据消息Chain中某个Command处理时可能会更新、处理Model信息还可以向MaverickContext中添加特定的参数接下来的Command就可以从MaverickContext获取更新处理之后的Model和这些特定的参数。    ICommand GetCommand(string name)    名称为*的Command被用作一个特殊的Command即当Dispatcher接收到一个无效的Command时将使用名称为*的Command来处理。我们在使用Maverick.Net框架时可以实现这个Command用于提示用户无效的操作信息。否则将产生一个404的异常。 其它 a) Command大小写敏感选项处理Command在大小写敏感方面的问题。首先Command对象用Hash Table缓存使用Command Name的Key值进行索引时存在大小写敏感问题。Command Name通过HttpRequest.ApplicationPath解析出来某些系统中可能会自动将ApplicationPath转换成大写。因此提供这个功能用于解决大小写敏感问题。 b) 两个特殊的CommandReloadCommand、CurrentConfigCommand参考Maverick.Net介绍篇。 c) 关于Dispatcher线程安全方面。详细的HttpHandler线程安全方面话题请参考其它相关资料。 第一点在初始化的一系列操作中我们可以看到很多地方将HttpContext对象作为参数传给工厂类而在Command、View、Transform等执行时刻函数Go()也用到HttpContext对象是否会存在线程安全问题其实在各个工厂类中以及Command、View、Transform等对象创建时刻如果使用到HttpContext内容只是用于获取ApplicationPath等对于整个应用而言全局的数据信息这在每个Http Request期间都是相同的而Command、View、Transform等执行时刻使用到的HttpContext对象都是从MaverickContext中获取在Dispatcher处理每个Http Request时都会使用当前请求的HttpContext创建一个新的MaverickContext将Command配置成Chain方式除外对象。因此对HttpContext的使用上Maverick.Net不会有线程安全方面的问题。 第二点ReloadCommand和CurrentConfigCommand这两个特殊Command是非线程安全的。Init()函数说明中提到过虽然Dispatcher对象是可复用的但在Application Pool中可能会有多个Dispatcher的实例。当提交一个ReloadCommand时会从Application Pool中取一个实例用于服务这个请求因此这个Dispatcher实例会根据当前的maverick.config配置重新进行初始化但这个初始化不会影响Application Pool中的其它实例其它实例使用的仍然是根据旧的maverick.config创建的对象。 其实它是违反了HttpHandler的一个线程安全规则不要使用成员变量或类似的机制用于不同的请求、线程间保存传递状态、数据信息。这种情况下可以用一个类似Observer模式解决或者对Dispatcher使用成员变量保存Command对象集合的方式做修改。 初始化、工厂类部分 这部分类图如下 图一初始化、工厂部分类图 Maverick.Net实现了2种类型的Transform和6种类型的View每种类型的Transform和View都对应到一个工厂类负责创建特定类型的实例。实际的Transform、View的创建操作永远都是由该类型的Transform、View对应的工厂对象完成的。 MasterFactory负责管理全部的Transform、View的工厂分别用两个HashTable成员保存并聚合了Transform、View的创建方法。因此当需要创建Transform或View对象时调用MasterFactory.CreateView()或者MasterFactory.CreateTransform()将请求提交给MasterFactory对象。MasterFactory负责根据Transform、View的类型找到对应的工厂对象然后调用工厂创建Transform或View。 ViewRegistry主要负责Global View的注册以供随时取用Global View对象以及对全局View的引用问题就是CreateViewsMap方法中的处理。ViewRegistry保存了一个MasterFactory的对象当要创建一个View时通过调用MasterFactory的方法完成。 关于Shunted View相关概念后面介绍。 Loader负责对全部创建工作的管理。经过上面类职责的了解可以知道其实Loader只需要管理好CommandFactory、MasterFactory、ViewRegistry这三个类就达到目的了。Loader在构造函数中完成初始化操作所以Dispatcher只需要创建Loader对象从Loader获取创建的Command集合就行。 Loader 初始化的执行过程大致如下图所述 Loader(XmlDocument doc, HttpContext httpContext) 构造函数完成全部初始化操作。 创建Command的容器HashTable时将根据Command大小写敏感配置分别进行处理。 SetupCoreModules() 分别创建各种类型的Transform Factory、View Factory调用这些工厂的初始化方法将工厂对象注册到viewFactories、transformFactories这两个HashTable成员中。 工厂的初始化方法给工厂对象提供一个初始化自己的机会但是现有的一些Transform、View的工厂中绝大部分初始化方法都不做什么实质性的事情。 LoadDocument(doc) 在调用这个方法之前各类工厂对象均已经被创建并完成初始化操作这个方法就是利用这些工厂对象根据maverick.config配置文件的XmlDocument对象doc创建各个框架对象。 LoadModules(XmlElement modulesNode)    这个函数根据maverick.config文件的配置创建自定义的Transform、View工厂对象以及自定义的ShuntFactory。 这是为扩展Transform、View的类型以及实现ShuntView提供的一种途径。假如需要扩展一种新的View类型就需要为这个View类型实现一个工厂类将这个工厂配置到maverick.config文件中这样在初始化的时候将创建这个工厂对象并注册到MasterFactory的Transform工厂集合和View工厂集合中。如果需要创建这类型的Transform或View将使用到这些工厂对象。 Modules节点配置示例如下  modules  transform-factory typemytran providermytran.mytranFactory, mytran     default-key-name valuemytran /  /transform-factory   view-factory typemyview providermyview.myviewFactory, myview     default-key-name valuemyview /   /view-factory/modules MasterFactory CreatePlainView(XmlElement viewNode) 读取View的类型属性根据类型值取对应的工厂使用工厂创建这种类型的View对象并返回。Plain View这个单词意指简单的View即直接由对应的工厂创建出来的View对象。 CreateView(XmlElement viewNode) 使用CreatePlainView函数得到IView对象之后再根据这个View是否有配置Transform、参数节点相应的将对象创建成ViewWithTransforms、ViewWithParams类型以便在View的执行时刻View对象的Go()方法内能处理Transform操作和参数。 CreatePlainTransform、CreateTransform 跟上面两个方法完全类似。 ViewRegistry、ViewRegistrySimple、ViewRegistryShunted 这三个类的关系从图一初始化、工厂部分类图中可以看出来。 在maverci.config文件中Command节点下面的View节点可以这样配置view nameloginRequired refloginForm/意思是将从全局View中引用id为loginForm的View对象。 这个引用关系并不是在执行时刻处理的而是在Maverick.Net初始化过程中完成。执行时刻处理可以这样描述如果Command根据Controller执行结果发现需要执行名称为loginRequired的View而这个View是对Global View中id为loginForm对象的引用所以从Global View中检索出这个loginForm的View对象然后执行它。这样的处理方式给框架带来复杂和不规范性而把这个操作放在初始化中则所有View的执行处理就统一起来了。Command对象聚合了一个或多个View对象在为Command创建聚合的View或View对象集合时如果某个View是对Global View对象的引用则从Global View中检索到这个View对象直接返回给Command避免Command在执行时刻从Global View中检索。这就是CreateViewsMap函数的作用。 Global View的创建是在创建Command之前完成的确保了在Command创建时刻能够引用到Global View对象。Global View的引用关系在初始化时刻已经被处理掉因此ViewRegistry、ViewRegistrySimple、ViewRegistryShunted这三个类也只在初始化的过程中用到在Maverick.Net正常的处理Http Request期间已经不再需要使用。 ViewRegistryShunted类用于在完成上述功能时对Shunted View特殊处理的支持。 Command      Command承担的工作很简单执行Controller的处理根据返回的结果选择对应的View运行这个View。 Command分为两类一类是没有Controller的对应CommandSingleView。这类Command不需要根据Controller的执行结果选择View因此这类Command有且只能有一个ViewCommand的执行其实就是直接对这个View进行呈现。Maverick.Net对这类Command使用一个NullController这个Controller不做任何事情只是为了保持Command行为的一致性。 另一类是有Controller的对应CommandMultipleViews。在初始化创建Command实例时已经为Command创建了Controller对象因此Command只需要调用这个Controller对象的Go()方法执行处理。 CommandBase提供了Command规范性的处理。CommandSingleView和CommandMultipleViews继承CommandBase主要实现GetView方法即怎样从Command对象持有的View对象中选择正确地View来执行。 View 几个简单的View。 NullView不做任何事情。可以用于Command节点下面没有配置任何View的情况但Maverick.Net目前没有这样使用如果Command下面没有View节点将产生异常。 TrivalView将Model以字符串的方式直接输出。如果某个Http请求的结果只是一段文本消息或者是输出一个文本文件、xml文件内容等可以使用这种类型的View。 ForwardView、RedirectView功能上基本是一样的。 ForwardView重定向到另外一个Command。它是直接在View的执行时刻使用Dispatcher获取Command对象调用Command.Go()方法。假如某个View需要重定向到名称为login的CommandView节点配置为view nameviewName commandlogin/。 RedirectView使用Response.Redirect()方法进行重定向所以重定向的目标可以是某个asp/aspx页面也可以是某个Command。假如需要重定向到名称为login的CommandRedirectView的实现方式为Response.Redirect(login.m)这种情况下可以将ForwardView看作是RedirectView的一种特例。RedirectView更倾向于重定向到某一个asp/aspx页面因为这类型的View在重定向之前会将需要传递的参数以GET的方式拼写到url中参数将包括IDictionary类型的Model对象和MaverickContext.Params。如果Model对象是String类型则RedirectView将把Model当作目标url而忽略view节点中配置的url。这类型的view配置示例如view nameviewName1 pathlogin.m/、view nameviewName2 pathdefault.aspx/。 如果整个项目以Maverick.Net架构是不需要使用RedirectView重定向到另外的asp/aspx页面的提供这种类型有利于与其它项目进行基于页面层次的整合或者类似的用途。 DocumentView这个View类型复杂些。 在类图结构中最基础的是DispatchedView这个类型的View完成asp/aspx等类型的页面文件转换成HTML的操作它是internal的类型只在框架内部使用实现的也是document类型View最基础的功能。 DocumentView聚合一个DispatchedView对象因此拥有DispatchedView的功能派生DocumentView主要是解决Model存放位置问题。它为abstract类型通过abstract类型的方法SetAttribute提供给子类解决如何传递Model。 ApplicationDocumentView、SessionDocumentView、RequestDocumentView都继承自DocumentView实现自己的SetAttribute方法分别使用Application、Session、HttpContext.Items作为存放Model的地方。Type为document类型的View在配置节点中通过scope属性确定该View属于这三种类型中的哪一种如果没有声明scope属性默认为RequestDocumentView类型。 以一个RequestDocumentView类型的对象来看在调用这个view的Go()方法的时候先在DocumentView.Go()方法处判断如果Model对象不为null则执行RequestDocumentView.SetAttribute()方法将Model放入HttpContext.Items中。这样这个view对应的aspx页面的服务器端代码就应当从HttpContext.Items中获取Model对象进行显示。接下来将调用聚合的DispatchedView对象的Go()方法将这个aspx页面解析成HTML。 XmlSerializingView单纯的从View的功能上看它也非常简单就是将Model反序列化之后的xml直接输出。这类型的View大都用于基于xml的网站方案中将Model序列化成xml之后可以使用XsltTransform将其转换成HTML。 以上介绍的几个类型的View的实例都由相应的View Factory创建可以说是一种简单类型的View对象。它们实现了几种基本形态View的功能Document类型的View复杂一点在View的显示过程中将使用到Model对象所以Document类型的View在类的结构上看起来也复杂一些。 剩下的两种类型的View就当作扩展类型来看待吧。 ViewWithParams有时候我们可能希望为某些View配置一些特殊的参数例如有两个功能Web页面98%都是相同的仅有微小的一点区别我们可能会希望只写一个页面通过给它们不同的参数使这一个页面运用在两个功能中。ViewWithParams聚合了一个IView对象它在本身的Go()函数中附加一些对参数的处理即将参数保存到MaverickContext这个上下文对象中然后再调用聚合IView对象的Go()方法。这样被ViewWithParams封装过的IView对象或者是对应的aspx页面中就能通过MaverickContext访问到这些参数。 参数的配置示例如下 view nameUserView pathUserView.aspx  param nameparam1 value??? /  param nameparam2 value??? //view 因为这种类型的View只是对基础类型View的一个封装扩展并且也许会有多个类型的View希望能够使用参数复用这样一个功能特性所以Maverick.Net并没有把这种封装过程放入到具体的某一个ViewFactory中而是放在了MasterFactory中处理。在MasterFactory.CreateView(XmlElement viewNode)方法中可以看到这一处理。 ViewWithTransforms这类型的View聚合一个IView和多个ITransform对象用于在View执行时对Transform处理。跟ViewWithParams类似用ViewWithTransforms封装IView对象的操作也是在MastrerFactory中处理。在Maverick.Net中虽然从表面上看起来View和Transform的衔接很紧密但Maverick.Net对View和Transform采用一种较松散的耦合方式来处理。 在现有的View类型中只有基于DocumentView类型的以及XmlSerializingView类型才能使用Transform操作。 ViewWithTransforms.Go()方法先将Transforms对象放入MaverickContext中然后调用聚合的IView对象的Go()方法。聚合的IView对象为DocumentView或XmlSerializingView类型对于DocumentView类型的将调用DispatchedView.Go()方法在DispatchedView.Go()和XmlSerializingView.Go()方法中都会通过MaverickContext.NextStep对象间接使用到Transform对象逐步完成输出内容的转换。 以一个DocumentView对象、具有一个Transform配置节点作为示例看一下Transform的处理过程。 每一个Transform对象都由位于它前面的一个驱动对象创建一个ITransformStep用于执行转换操作。第一个Transform的ITransformStep由DispatcheView创建。 DispatcheView执行时先使用第一个Transform对象创建ITransformStep使用Server.Execute()将DispatcheView的aspx页面转换成HTML放入ITransformStep创建的MemoryStream中然后调用ITransformStep的Go()方法。随后的每一个ITransformStep在Go()方法中首先使用下一个Transform对象创建下一个ITransformStep然后从MemoryStream读取上一个驱动对象放入的HTML用它对应的Transform配置节点中的key属性值作为Key值将HTML放入HttpContext.Items中最后使用Server.Execute()方法执行它对应的Transform对象的aspx页面将输出的HTML放入下一个ITransformStep的MemoryStream。 当执行达到最后一个Transform位置时它后面再没有其它Transform因此创建LastStep类型的ITransformStep对象这个对象的Go()方法是一个空操作但是它将HttpContext.Response.OutputStream作为MemoryStream的替代因此最后一个Transform的aspx页面在使用Server.Execute()方法执行后就直接输出到Response.OutputStream中了。 理解上面的处理过程之后会有一个疑问就是只看到了最后一个Transform对应的aspx执行后的HTML代码发送给客户端它之前的Transform对应的aspx页面、View对应的aspx页面执行后的HTML代码呢从这个过程中我们只能看到这些HTML代码被依次放入HttpContext.Items中并没有看到向客户端输出。实际上从Maverick.Net的示例项目Friendbook中取一个View最后一个Transform相关联的aspx页面看一下就知道了在这个aspx页面里会看到类似%Context.Items[wrapped]%的服务器端语句就是这个语句从Context.Items中取出一段HTML内容并输出。这样就可以明白了最后一个Transform对应的aspx页面执行后的HTML代码自然就包括了它前面的Transform、View执行后的HTML。 View对象本身的关系可能会有点复杂例如可能创建的一个ViewWithTransforms对象将会聚合一个RequestDocumentView而这个RequestDocumentView又聚合一个DispathedView。另外在View的执行时刻跟Transform的转换结合在一起。所以一个IView对象的Go()方法感觉上转来转去使对这个处理过程的理解产生疑惑。通过上面的描述好好的理解这些对象的职责把它们的关系梳理清楚之后你会发现其实还是很简单的。 ShuntedView 整体上来看ShuntedView也是比较简单的。普通类型的View通过一个name属性作为Key值ShuntedView则必须使用name属性加上一个mode属性一起才能作为Key值。这是用于实现多语言之用比如同一个View UserQuery可能需要有中文、英文等语言支持将语言代码作为Mode使用UserQuery ch获取中文版本使用UserQuery en获取英文版本。相应的View的配置节点类似如下 command nameUserQuery    controller class /    view nameloginRequired refloginRequired/    view namesuccess typedocument pathUserQuery-ch.aspx modech        transform path/    /view    view namesuccess typedocument pathUserQuery-en.aspx modeen        transform path/    /view/command Maverick.Net在多语言的实现方式上并不理想。一个View如果对应于每一个语言都需要写另外一个页面这种方式只能说太笨了。这种情况下如果View需要修改任何时候都将需要对不同语言版本的页面同时修改。 下面这副图帮助理解一下Shunt处理过程。 目前Maverick.Net并没有使用ShuntedView在Loader的构造函数中创建的是ViewRegistrySimple而不是ViewRegistryShunted对象。如果使用多语言应当在这个地方使用ViewRegistryShunted上面的图就是基于这种情况下的处理过程描述。 具体的实现细节根据这个序列从代码上可以看出来下面讲的是大致的思路。ViewShunted仅仅是聚合一个IShunt对象并实现IView接口真正的操作是由IShunt对象完成的。在多语言的运用情况下IShunt对象为LanguageShunt类型这个类型的对象维护了一个HashTable成员modes它以View配置节点的mode值作为Key将name相同而mode值不同的多个IView对象保存在这个HashTable中。这样name相同而语言版本不同的多个IView对象通过ViewShunted的封装从外部看起来它就成为一个IView对象了。在上面的xml示例配置中名称为UserQuery的ICommand对象将拥有两个注意不是三个IView对象一个为loginRequired另外一个为ShuntedView类型的success。这样对于ICommand对象执行时对ShuntedView的处理方式上也是规范的ICommand对象无需了解后面的细节。ViewShunted类型的View在执行时尝试从Request.Headers对象中取语言代码然后根据这个语言代码获得对应的IView对象继而调用这个IView对象的执行方法。 Transform 其实经过上面对ViewWithTransforms执行过程的理解对于Transform对象也就没有什么悬念了。 尽管DocumentTransform在概念上理解起来比较牵强因为view的aspx执行之后就是HTML了感觉上不再需要什么转换处理Maverick.Net的示例项目Friendbook中将Transform作为几乎所有工作页面的一个整体包装页面的用途。也许你还能发现其它有意思的用处。 对于基于xml的网站XsltTransform的作用理解起来就非常直接了。对XsltTransform有几种方式的用法 1. 将View配置成document类型用path直接指定一个静态xml文件然后使用xsl解析。例如 view typedocument pathwelcome.xml  transform pathoutside.xsl//view 2. 将View配置程xmlXmlSerializingView类型把Model反序列化成xml使用xsl解析。 3. 将View配置程trivial类型由Controller直接构造xml然后用xsl解析。 4. 将View配置成xml类型View并不输出任何xml直接使用Transform处理。这种情况通常第一个Transform输出xml后面的Transform解析成HTML。这种跟1基本完全一样。 对xml类型的View使用XsltTransform转换的处理过程跟DocumentTransform完全一样。 在这个处理的Chain上IView对象是起点。前面提到过View跟Transform之间是一种较松散的耦合方式这样IView对象无需去管理自己有多少个Transform应该怎样一步一步的执行转换以及将最终的结果发送给客户端。IView对象只需要完成自己的职责它知道在它的后面一定有其它的对象来处理上面这些事情所以IView处理完之后将它输出的视图代码抛给下一个对象即可。 LastStep对象是Chain的终结者负责将最后的输出发送给客户端浏览器。 大概考虑到无论是Server.Execute()或者System.Xml.Xsl.XsltTransform.Transform()方法都可以向Stream直接输出Maverick.Net在Chain处理上采用一个Stream类型的成员变量向后传递输出内容。既然这样在Chain上每一个执行步骤中动态创建一个ITransformStep就成为一种必要。 Controller  Maverick.Net提供一些Controller的基础类用于实现不同用途下的Controller。    ...... posted  MAVERICK.NET初窥 ASP.NET出来了很久了微软一直强调其ASP.NET是给WEB开发带来了很多的方便code-behind的方式优化了代码的结构等云云。然而当我们真正用ASP.NET来开发时我们发现我们还是陷入到了混乱之中如 MVC如何实现虽然code-behind从某种意义上说是实现了C和V的分离但是还是远远不够 页面间的flow如何处理还是在代码中采用了hard-code的方法要修改页面的跳转必须修改源代码页面间的关系不能清楚地表现和可配置 多语言怎么实现虽然可以用资源文件来解决但是一个单词的中文和英文的长度不一致很多时候还是要重写2个页面根据不同的浏览器多语言配置如何实现这些不同页面的选择也不能很好解决 公用页面模块如何尽量提高可复用性虽然微软也提供了User Control但是它始终和ASPX有很多不一样很难对2者共同对待 等 微软也意识到了这些问题于是出了个UIPB但是UIPB也仅仅解决了一小部分的问题如前面所说的页面跳转的问题。坦白地说我认为UIPB的设计初衷实在是一个错误的方向。UIPB主要解决一个项目WEB表现层和WINFORM表现层如何能够最大范围的复用的问题。试问有多少项目会有这样的需求诚然有些项目确实需求2种表现层但是也是各自完成不同的任务居多。即使是有这种需求我们也知道WINFORM和WEB有太多的不同有些WEB中多个页面跳转完成的事情在WINFORM中仅仅是一个窗口就可以完成。另外WEB中要尽量少用弹出窗口而WINFORM没有这种限制。因此我认为UIPB还是没有解决WEB层的大多数问题不能适应现在商业的WEB项目开发。 那么我真的开始苦恼了.NET项目中应该用什么来实现表现层看看J2EE阵营他们确实也苦恼但他们苦恼的是面对那么多的开源解决方案应该选择那个。有的时候真想改姓J2EE算了呵呵。 终于前些天看到了MAVERICK.NET项目实际上这个项目也是从J2EE的MAVERICK项目port过来的。我把Maverick.NET当了下来研究了几天总算心理稍稍平了点。从我现在对MAVERICK.NET的浅薄的了解中我认为它至少解决了以下几个问题 完全的MVC实现 页面间的跳转问题可以通过一个统一的配置文件建立期间的联系 页面模块可以灵活地通过配置文件plug到多个View中去 多语言的幽雅实现 页面的模板可以使用XSLT等转换技术 下面我从MAVERICK.NET中自带的一个简单例子来简单说明 配置IIS将.m的文件用ASP.NET引擎来解析 配置web.config加入以下语句 configSections     sectionGroup nameMaverick         section nameDispatcher typeSystem.Configuration.NameValueSectionHandler,system, Version1.0.3300.0, Cultureneutral, PublicKeyTokenb77a5c561934e089, Customnull /     /sectionGroup /configSections Maverick     Dispatcher         add keyconfigFile valuemaverick.config /         add keycurrentConfigCommand valuecurrentConfig /         add keyreloadCommand valuereload /         add keylimitTransformsParam valuemaxTransforms /         add keycommandCaseSensitivity valueinsensitive /     /Dispatcher /Maverick  /system.web            httpHandlers         !-- 该工程的任何页面访问都会首先执行该httpHandler实际上是一个dispatcher             来根据maverick.config的配置来启动相关页面 --         add verb* path*.m typeMaverick.Dispatcher, Maverick /     /httpHandlers  /system.web 配置maverick.config文件 maverick version2.0 default-view-typedocument default-transform-typedocument     commands         command nameDefault.aspx             view namesuccess typetrivial                 transform path~/Wrapper.aspx/    !-- 这就是一个标题也就是嵌入的公用页面模块 --             /view             view nameapril path~/April.aspx                 transform path~/Wrapper.aspx/             /view                view namebutton path~/Button.aspx                 transform path~/Wrapper.aspx/             /view         /command     /commands /maverick   建立Default.aspx文件在code-behind文件中添加一个以下方法 protected string viewName success; // 默认显示名为“success”的view public override string Go(Maverick.Flow.IControllerContext cctx) {     return this.viewName; } 在一个button的时间代码中添加如下代码当button按下时就会根据maverick.config的配置来显示相应内容 private void Button1_Click(object sender, System.EventArgs e) {     this.viewName button; //按下button后就会显示名为button的view } 在一个日历控健的Selection_change事件代码中添加如下代码 private void Calendar1_SelectionChanged(object sender, System.EventArgs e) {     if (this.Calendar1.SelectedDate.Month 4)         this.viewName april;    // 当该代码执行时就会转向名为april的view }   建立April.aspx、Button.aspx、Wrapper.aspx页面 以上的例子至少体现了Maverick的页面跳转配置实现、公用页面模块灵活配置的2个优点因为这是一个最简单的实现所以其他的特点没有完全展现。关于MAVERICK.NET的应用、以及under the hook我将在后续的post中描述。 转载于:https://www.cnblogs.com/lsgoodsun/archive/2007/08/13/854172.html
http://www.zqtcl.cn/news/647406/

相关文章:

  • 学校网站怎么建设兄弟网络(西安网站建设制作公司)
  • 长春市城乡建设局网站photoshop破解版下载免费中文版
  • 吕梁网站设计天津高端网页制作
  • 建一个网站做cpa联盟做淘客的网站都有哪几个
  • 中国建设银行网站对公业务wordpress 文章归档页面
  • 东软 网站群平台建设用个人电脑做网站服务器
  • 音乐播放网站开发pc端营销网站的关键字
  • 江门网站推广宿州官方网站建设
  • 企业网站建设策划书范文江苏高端网站建设
  • 网站开发 浏览器济宁网站建设服务
  • 整套网站建设网站开发中如何实现gps定位
  • 网站建设计划表福州自助建站
  • 网站做的比较好的公司吗2017年做网站多少钱
  • 基础展示营销型型网站重庆百度总代理
  • 网站建设 技术可行性这是我自己做的网站
  • 西安网站策划关键词优化哪家好
  • 能看建设动漫黄图的网站海外仓一件代发平台
  • 做网站都需要了解什么大连福佳新城2026年建站吗
  • php 网站部署到服务器泉州模板建站哪家好
  • 网站服务器上的跳转选择怎么做网站是怎么建立的
  • 网站后台目录如何保护公司网站建设需要要求什么软件
  • 四川省建设厅网站官网自己做的网站能上传到凡科吗
  • 米拓网站建设-app定制开发免费个人建站系统
  • 网站改版公司如何帮公司做网站
  • 曹县汽车网站建设网站怎么做才 吸引人
  • 河南周口东宇网站建设wordpress怎么重新安装插件
  • wordpress无法上传主题南通做网站优化公司
  • 做彩票网站能挣到钱吗南充市房产信息网
  • 沧州北京网站建设金华网站建设哪个公司好点
  • 北京朝阳建站优化wordpress主题访问慢