阅读目录:

  • 1.需求背景介绍(Model元数据设置项应该与View绑定而非ViewModel)

    • 1.1.确定问题域范围(可以使用DSL管理问题域前提是锁定领域模型)
  • 2.迁移ViewModel设置到外部配置文件(扩展Model元数据提供程序)
    • 2.1.实现元数据提供程序(简单示例)

1.需求背景介绍(Model元数据设置项应该与View绑定而非ViewModel)

使用ASP.NETMVC构建普通的中小型站点可以使用简单的Model元数据设置方式来控制ViewModel如何显示在View中,但是复杂的应用场景不会这么简单的就能完成;大型站点的ViewModel的体积非常大,真的大的超乎我们的想象(当然这里面有历史原因),这么大的一个显示实体我们需要在不同的页面中呈现它会非常的棘手;然而小型站点不太会遇见ViewModel在几十个页面中显示的情况出现,一般页面也就是几十个差不多了;

在大型电子商务应用中,UI层的一个ViewModel不仅用来呈现数据还充当着与远程SOA接口通讯的DTO作用,如果为了结构清晰完全可以将ViewModel与DTO分开,但是有时候我们确实需要考虑额外的性能开销(有时候我们只能接受历史遗留的问题,技术债务累积多久就要还多久);

这篇文章将讲解如何利用ASP.NETMVC开发大型站点时ViewModel中设置的元数据设置项随着不同的业务View不同而调用不同的元数据设置项,简单的讲也就是我们不会直接在ViewModel上应用元数据控制特性,而是通过将Model元数据设置项与具体的View绑定的方式来控制它在不同的View中运用不同的元数据控制项,元数据控制特性不会和具体的ViewModel绑定而是和具体的View绑定,因为只有View才是固定呈现什么内容,而ViewModel是用来共用的显示数据项的容器,我将通过本篇文章来讲解如何设计这样的高扩展性的ASP.NETMVC ViewModel使用结构;

1.2.确定问题域范围(可以使用DSL管理问题域前提是锁定领域模型)

在考虑使用配置文件将所需要的东西配置起来的时候,我们需要先确定到底需要将什么配置起来;这就需要我们先确定问题域,其实这也就是面向DSL编程的方法;

DSL:简单理解为面向特定领域的语言;该语言主要用来解决特定领域的实现问题,刚开始我们可以会把这个概念定义的过于庞大,希望能通过DSL解决一切领域问题,其实这是错误的;DSL其实是一小部分领域问题的提炼,如:我们这里的将ModelMetadata设置特性从原来定义在ViewModel上的迁移到外部去,这其中的主要问题域就是将ModelMetadata设置项与View绑定,而不是ViewModel;

只有先准确的找到问题域之后我们才能设计DSL来充分的表达这个问题域,通过XML能很好的表达任何特定领域结构的模型,当然你完全可以自己去设计DSL;

目前对ViewModel中设置的元数据控制特性都会作用于使用该ViewModel的所有View,我们要解决的问题是将上图中的ModelMetadata域提取出去与View进行绑定,从而得到一个干净的ViewModel和灵活的面向View的元数据控制功能;当我们成功迁移之后,我们将得到下图中的结构;

最终我们会得出这样的一个满足实际需求的结构;

2.迁移ViewModel设置到外部配置文件(扩展Model元数据提供程序)

要想成功迁移设置项我们必须要搞清楚ASP.NETMVC中Model元数据提供程序的原理,这样我们才能将原来获取元数据的方式改变成我们自己的获取策略;在元数据提供程序对象模型中主要的功能分为两部分(这里我们只介绍获取元数据过程):

我们需要将BuildModelMetadata功能区域换成我们自己的策略;

这样我们就可以将一组强大的元数据提供程序植入到ASP.NETMVC框架的内部;

通过CustomModelMetadataProviderFactory创建用于获取任何一个外部类型的元数据提供程序对象,比如:CustomModelMetadataProviderWithDb(用于数据库的接口),CustomModelMetadataProviderWithConfig(用户配置文件),CustomModelMetadataProviderWithService(远程Service);

迁移ModelMetadate缓存数据(紧要关头可以进行内存优化)

在ASP.NETMVC内部提供了用来获取某个ViewModel的ModelMetadata的提供程序,通过该入口我们将可以把Model元数据缓存在我们自己的容器中,当然绝佳的缓存位置就是当前应用服务器的本地进程,这里是最好的缓存位置,我们缓存元数据主要不是为了改变它的存放位置而是要改变它获取的途径和方式,这样其实会有很多好处,比如:通过工具化管理内存中的缓存数据,对其进行压缩等等,因为你已经可以控制其获取元数据的过程,这在紧要关头可能就是救命稻草,这里只是一点扩展性的介绍,当然要看具体的需求了,不过这确实是一个好的思路;

2.1.实现元数据提供程序(简单示例)

View、ViewModel、ModelMetadata 映射设计:

 using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc; namespace MvcApplication4.Seed
{
public enum View
{
HomePage_Index,
HomePage_Edit
}
public enum ViewModel
{
Customer
}
public class ViewMappingModelMetadata
{
public View View { get; set; }
public ViewModel ViewModel { get; set; }
public ModelMetadata Metadata { get; set; }
} public class ViewMappingModelMetadataCollection : Dictionary<View, List<ViewMappingModelMetadata>>
{
private static ViewMappingModelMetadataCollection coll = new ViewMappingModelMetadataCollection();
static ViewMappingModelMetadataCollection()
{
//在Homepage下的视图———来自外部文件的接口,这里只是示例显示
coll.Add(View.HomePage_Index, new List<ViewMappingModelMetadata>());
coll[View.HomePage_Index].Add(new ViewMappingModelMetadata()
{
View = View.HomePage_Index,
ViewModel = ViewModel.Customer,
Metadata =
new ModelMetadata(CustomModelMetadataProviderWithConfig.CurrentProvider, typeof(Models.Customer),
() => { return new Models.Customer().CustomerId; }, typeof(string), "CustomerId")
{
DisplayFormatString = @"HomePage\DisplayName:{0}"
}
});
//在EditCustomer下的视图——来自外部文件的接口,这里只是示例显示
coll.Add(View.HomePage_Edit, new List<ViewMappingModelMetadata>());
coll[View.HomePage_Edit].Add(new ViewMappingModelMetadata()
{
View = View.HomePage_Edit,
ViewModel = ViewModel.Customer,
Metadata = new ModelMetadata(
CustomModelMetadataProviderWithConfig.CurrentProvider, typeof(Models.Customer),
() => { return new Models.Customer().CustomerId; }, typeof(string), "CustomerId")
{
DisplayFormatString = @"Edit\DisplayName:{0}"
}
});
}
public static ViewMappingModelMetadataCollection Current
{
get { return coll; }
} public ModelMetadata GetMetadataByView(View view, ViewModel model)
{
var metaList = from item in coll[view] where item.ViewModel == model select item.Metadata;
return metaList != null && metaList.Count() > ? metaList.LastOrDefault() : null;
}
}
}

这两段是要被放到框架内部去完成的,这里只是为了演示其元数据的设置原理,所以简单这么写;

System.Web.Mvc.ModelMetadataProvider 实现自定义元数据提供程序:

 using System;
using System.Collections.Generic;
using System.Web.Mvc; namespace MvcApplication4.Seed
{
public class CustomModelMetadataProviderWithConfig : System.Web.Mvc.ModelMetadataProvider
{
private static CustomModelMetadataProviderWithConfig provider = new CustomModelMetadataProviderWithConfig();
public static CustomModelMetadataProviderWithConfig CurrentProvider
{
get { return provider; }
} public override IEnumerable<ModelMetadata> GetMetadataForProperties(object container, Type containerType)
{
throw new NotImplementedException();//复杂类型实现,属性的循环获取
} public override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName)
{
throw new NotImplementedException();//复杂类型实现,属性的循环获取
} public override ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType)
{
if (modelAccessor == null) return null;
if (System.Web.HttpContext.Current.Session["viewname"] == null) return null;
var result = ViewMappingModelMetadataCollection.Current.GetMetadataByView(
(View)System.Web.HttpContext.Current.Session["viewname"], (ViewModel)System.Web.HttpContext.Current.Session["viewmodel"]);
if (modelAccessor != null)
result.Model = modelAccessor().GetType().GetProperty("CustomerId").GetValue(modelAccessor());
return result;
}
}
}

Customer模型定义:

 public class Customer
{
public string CustomerId { get; set; }
}

在模型上我们没有应用任何一个 元数据控制特性,但是我们将在界面上看到效果;

View 视图定义:

 @model  MvcApplication4.Models.Customer 

 <table>
<tr>
<td>
<h2>编辑模式.</h2>
<h3>@Html.DisplayForModel(Model.CustomerId)</h3>
</td>
</tr>
</table> @model MvcApplication4.Models.Customer <table>
<tr>
<td>
<h2>显示模式.</h2>
<h3>@Html.EditorForModel(Model.CustomerId)</h3>
</td>
</tr>
</table> 这是两种模型的呈现方式;

我们自动设置的元数据已经起到效果了;

作者:王清培

出处:http://www.cnblogs.com/wangiqngpei557/

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

.NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序)的更多相关文章

  1. 迁移Model元数据设置项

    .NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序) 阅读目录: 1.需求背景介绍(Model元数据设置项应该与View绑定而非ViewModel) 1 ...

  2. 大型分布式架构设计与实现-第一章SOA(面向服务的体系架构)

    拜读了大型分布式架构设计与实现,觉得该书作为入门不错,但内容过于简单,描述过于琐碎,小节之间连续性不强,不适合深入钻研学习.但为了更多的希望向架构师行业靠拢的工程师学习需要,本博客将对上书进行简化讲解 ...

  3. dba和运维专家们说有丰富的大型分布式系统架构设计经验纯属扯淡

    如果,一开始就从事dba和运维的专家们说他们有丰富的大型分布式系统架构设计经验,那纯属扯淡.除非,他们从是从开发专家或者架构师转型而来,那么他们才有资格说自己有丰富的大型分布式系统架构设计经验. 运维 ...

  4. 大并发server架构 &amp;&amp; 大型站点架构演变

    server的三条要求: 高性能:对于大量请求,及时高速的响应 高可用:7*24 不间断,出现问题自己主动转移.这叫fail over(故障转移) 伸缩性:使用跨机器的通信(TCP) 另外不论什么网络 ...

  5. 亿级流量场景下,大型缓存架构设计实现【1】---redis篇

    *****************开篇介绍**************** -------------------------------------------------------------- ...

  6. 千万PV级别WEB站点架构设计

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://sofar.blog.51cto.com/353572/1369762 高性能与多 ...

  7. .Net站点架构设计(八)測试

    .Net站点架构时间(八)測试 一般而言.总体測试策略是:先针对部分系统进行性能及压力測试,得到各部分的峰值处理性能:再模拟总体流程測试,此时倒不用依照峰值跑,重点測试总体业务流程及业务预期负荷. 在 ...

  8. Web站点架构设计考虑的因素

    转自http://blog.csdn.net/moshengtan/article/details/8990052 1    Web负载均衡 1.1 - 使用商业硬件实现 最经常使用的F5 与citr ...

  9. dubbo框架----探索-大型系统架构设计(图解)

    对于高并发系统的架构要求: 1. 负载均衡 2.高并发 3.高可用 4.面向服务架构 (Dubbo框架使用) 5.分布式缓存 (redis分布式缓存) 6.分布式全文检索 (solr分分布式全文检索) ...

随机推荐

  1. 1Z0-053 争议题目解析688

    1Z0-053 争议题目解析688 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 688.Which two statements are true about the compr ...

  2. 数据库join方式分析

    前言    不管是博客园还是CSDN,看到很多朋友对数据库的理解.认识还是没有突破一个瓶颈 ,而这个瓶颈往往只是一层窗纸,越过了你将看到一个新世界.    04.05年做项目的时候,用SQL Serv ...

  3. IIS下配置PHP

    首先下载Windows的PHP安装包.随后将该包解压至C:\PHP.完成上面的步骤后,将C:\php目录下的php.ini-dist文件改名为php.ini,然后拷到C:\Windows目录下. 用记 ...

  4. Compensating Transaction Pattern(事务修正模式)

    Undo the work performed by a series of steps, which together define an eventually consistent operati ...

  5. Microsoft Visual Studio 插件

    AnkhSVN BatchFormat CodeMaind Nuget Package Manager

  6. 整数压缩编码 ZigZag

    在分析Avro源码时,发现Avro为了对int.long类型数据压缩,采用Protocol Buffers的ZigZag编码(Thrift也采用了ZigZag来压缩整数). 1. 补码编码 为了便于后 ...

  7. 文件权限及chmod使用方法

    文件权限 在linux在,由于安全控制需要,对于不同的文件有不现的权限,限制不同用户的操作权限,总共有rwxXst这一些权限,我们经常使用到的是rwx,对于文件和文件夹而言,他们代表着不同的含义 对于 ...

  8. Linux环境中Openfire安装指南

    Linux环境中Openfire安装指南 安装环境: 安装软件:Openfire 4_1_0 http://download.igniterealtime.org/openfire/openfire_ ...

  9. WebApi设置SessionState为Required

    public override void Init() { //在注册管道事件中 require session state //只能在引发“HttpApplication.AcquireReques ...

  10. Android使用ViewPager实现左右循环滑动及轮播效果

    边界的时候会看到一个不能翻页的动画,可能影响用户体验.此外,某些区域性的ViewPager(例如展示广告或者公告之类的ViewPager),可能需要自动轮播的效果,即用户在不用滑动的情况下就能够看到其 ...