阅读目录:

  • 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. 使用yield进行异步流程控制

    现状 目前我们对异步回调的解决方案有这么几种:回调,deferred/promise和事件触发.回调的方式自不必说,需要硬编码调用,而且有可能会出现复杂的嵌套关系,造成"回调黑洞" ...

  2. 【JavaWeb】MVC案例之新闻列表

    MVC案例之新闻列表 作者:白宁超 2016年6月6日15:26:30 摘要:本文主要针对javaweb基本开发之MVC案例的简单操作,里面涉及mysql数据库及表的创建,以及jsp页面和servle ...

  3. centos7 mysql数据库安装和配置

    一.系统环境 yum update升级以后的系统版本为 [root@yl-web yl]# cat /etc/redhat-release CentOS Linux release 7.1.1503 ...

  4. Solr学习总结(五)SolrNet的基本用法及CURD

    上一篇已经讲到了Solr 查询的相关的参数.这里在讲讲C#是如何通过客户端请求和接受solr服务器的数据, 这里推荐使用SolrNet,主要是:SolrNet使用非常方便,而且用户众多,一直都在更新, ...

  5. android防止内存溢出浅析

    Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小一般是16M.但是Android采用的是Java语言编写,所以在很大程度上,Android的内存机制等同于Java的内存机制,在刚开始开 ...

  6. do{...}while(0)的妙用

    在学习第一门编程语言时,就已经介绍了顺序分支.条件分支.循环分支.比如循环分支有for.while.do-while语句.在随后的学校及工作中,如果手工循环一般使用for.while,很少使用do-w ...

  7. HTML5 Application cache初探和企业应用启示

    Application Cache 在自己做的开源项目( https://github.com/etoah/Lucien ) 用到了HTML5 的Application Cache,现总结如下: 目录 ...

  8. Xamarin.Android之引导页的简单制作

    0x01 前言 对于现在大部分的APP,第一次打开刚安装或更新安装的APP都会有几个引导界面,通常这几个引导页是告诉用户 APP有些什么功能或者修改了什么bug.新增了什么功能等等等. 下面就用Xam ...

  9. C标准头文件<signal.h>

    信号即异常,或者理解为中断,一个进程接收到一个信号,如果没有处理机制,就会按照默认的处理方式进行处理,而默认的处理方式通常是终止当前进程或忽略该信号.当然,程序也可以编写相应的处理信号的函数,一旦接收 ...

  10. codevs 1021 玛丽卡(spfa)

    题目描述 Description 麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复. 因为她和他们不住在同一个城市,因此她开始准备她的长途旅行. 在这个国家中每两个城市之间最多只有一条路相通,并且我们 ...