访问级别与成员

在C# 4出现之前,我们也完全可以构造一个Model类型作为视图的模型,例如:

public class IndexModel
{public string Title { get; set; }
}

使用这种做法便完全可以正常运行通过了。那么为什么具体类型能够正常工作,而匿名类型却失败了呢?“按常理推断”它们不都是普通的类型,然后访问它们的属性吗?我们用ILSpy查看使用匿名类型编译后的结果,可以发现匿名类型与上面的IndexModel有一个重要的不同之处:

由于是“匿名类型”,显然它的访问级别应该是internal的,这样它就能对外“隐藏”起来了。但是这就给ASP.NET MVC的视图带来了麻烦。因为ASP.NET MVC的视图会在运行时动态地编译aspx为额外的dll,因此它是无法访问到Controller所在程序集的internal成员的。经试验,如果我们将之前的IndexModel的访问级别修改为internal便会得到相同的结果。

额外提一句,类似的代码在Mono下却可以运行通过。这意味着在动态访问对象成员的时候,Mono和.NET在访问级别方面的检查是有所不同的。虽然在这个情景里Mono更方便,但理论上说,.NET的做法实则更合理。

使用NuGet安装Mono.Cecil

Mono.Cecil是Mono的组件之一,用来编辑.NET程序集文件。我们可以用它来打探一个.NET程序集内部的结构,就像反射那样,只不过并不需要将程序集加载进来,Mono.Cecil只是读取文件物理内容而已。例如,上图所用的ILSpy便用到了Mono.Cecil。更重要的是,Mono.Cecil可以修改并保存程序集,这便可以让我们实现各种奇形怪状的要求。像这篇文章所提到的,只不过是小试牛刀而已。

Mono和.NET是二进制兼容的,因此我们可以直接把Mono下的Mono.Cecil.dll复制并引用到.NET程序里。不过这么做还是麻烦了,如今在.NET平台上使用各种组件已经有更方便的做法:使用包管理器。.NET平台下的包管理器叫做NuGet,是由SubText的作者,后来被微软聘用作ASP.NET MVC程序经理的Phil Haack带头开发的开源项目。NuGet提供了Visual Studio的扩展,同时也有基于PowerShell的命令行。这里我们就从Visual Studio的扩展开始使用吧。

创建一个名为PublicAnonymous的控制台项目,并选择Reference - Manage NuGet Packages:

搜索Mono.Cecil,并安装即可:

NuGet会自动处理组件之间的依赖及项目的配置,您也可以自己把玩一番。

使用Mono.Cecil修改程序集

有了Mono.Cecil我们便可以修改程序集了,只需数行代码:

static void Main(string[] args)
{var asmFile = args[0];Console.WriteLine("Making anonymous types public for '{0}'.", asmFile);var asmDef = AssemblyDefinition.ReadAssembly(asmFile, new ReaderParameters{ReadSymbols = true});var anonymousTypes = asmDef.Modules.SelectMany(m => m.Types).Where(t => t.Name.Contains("<>f__AnonymousType"));foreach (var type in anonymousTypes){type.IsPublic = true;}asmDef.Write(asmFile, new WriterParameters{WriteSymbols = true});
}

首先,从参数中获取需要修改的程序集名称,找到所有的匿名类型,并将其访问级别设为Public后保存。保存的时候将WriteSymbols参数设为true,这样它也会同时修改pdb文件——这很重要,否则修改后的程序集无法和pdb文件内容相对应,便无法调试了。换句话说,Mono.Cecil也能正确处理pdb文件。

最后,只要在ASP.NET MVC网站编译时使用这个项目即可,只需配置一下它的Post Build事件:

再次编译并运行程序,即可得到正确结果。再拿ILSpy来检查一番:

感谢作者,本文转载至:http://blog.zhaojie.me/2011/09/aspnet-mvc-dynamic-model-mono-cecil.html

使用Mono.Cecil改变访问级别相关推荐

  1. 使用Mono.Cecil辅助ASP.NET MVC使用dynamic类型Model

    使用Mono.Cecil辅助ASP.NET MVC使用dynamic类型Model 2011-09-06 00:21 by 老赵, 8645 visits 这也是之前在珠三角技术沙龙上的示例之一,解决 ...

  2. 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习)

    原文:利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习) Mono.Cecil是一个强大的MSIL的注入工具,利用它可以实现动态创建程序集,也可以实现拦截器横向切入动态方法,甚至还 ...

  3. 巧用Mono.Cecil反射加载类型和方法信息

    最近在做服务的细粒度治理,统一管理所有服务的方法.参数.返回值信息.方便后续的各个模块之间的对接和协作. 目前系统中所有的服务,管理到接口契约粒度,即服务接口声明和服务接口实现.要做服务的细粒度治理: ...

  4. 编译时MSIL注入--实践Mono Cecil(1)

    紧接上两篇浅谈.NET编译时注入(C#-->IL)和浅谈VS编译自定义编译任务-MSBuild Task(csproject),在第一篇中我们简单研究了c#语法糖和PostSharp的MSIl注 ...

  5. 运用Mono.Cecil 反射读取.NET程序集元数据

    CLR自带的反射机智和API可以很轻松的读取.NET程序集信息,但是不能对程序集进行修改.CLR提供的是只读的API,但是开源项目Mono.Cecil不仅仅可以读取.NET程序集的元数据,还可以进行修 ...

  6. Mono.Cecil使用示例之使指定程序集成为UnityEditor.dll的友元程序集

    Mono.Cecil使用示例之使指定程序集成为UnityEditor.dll的友元程序集 Mono.Cecil是一个开源的库,使用Mono.Cecil可以非常方便的在代码中修改C#程序集.在Unity ...

  7. Mono.Cecil C#代码注入

    先标记下 有时间再写 转载于:https://www.cnblogs.com/docomo/archive/2013/06/06/3122157.html

  8. Mono 2.0正式发布了

    Mono官网:http://mono-project.com/ 2.0 Release Notes: http://www.mono-project.com/Release_Notes_Mono_2. ...

  9. 几篇关于Cecil混淆程序集的文章

    Paul Mason (via Chris Alcock)几篇关于保护源码和利用Cecil混淆演示的文章 Protecting your precious code!, Protecting your ...

  10. 国内 Mono 相关文章汇总

    一则新闻<软件服务提供商Xamarin融资1200万美元>,更详细的内容可以看Xamarin的官方博客Xamarin raises $12M to help you make better ...

最新文章

  1. 用GDB调试程序(四)
  2. python基础——注释、字符串、输出换行
  3. MySQL内核调试_MySQL内核技术之“Opt_trace_系列”
  4. java合并单元格同时导出excel
  5. keras构建卷积神经网络_在Keras中构建,加载和保存卷积神经网络
  6. vim 删除多行_Vim神器的五个高效插件,新老司机别错过!
  7. java json 工具类_Java中JSON处理工具类使用详解
  8. Drupal第三方库jQuery UI起死回生,多个漏洞影响网站、企业产品等
  9. 渐开线曲线方程c语言,proe常用曲线方程大全
  10. 袋鼠云研发手记 | 开源·数栈-扩展FlinkSQL实现流与维表的join
  11. 无法打开csproj,因为此版本的应用程序不支持其项目类型 csproj
  12. 如何电脑开机自动宽带链接网络连接服务器,电脑开机怎么设置宽带自动连接_宽带连接设置方法 - 驱动管家...
  13. MW6208U盘量产问题
  14. 安卓开机画面_领克的开机画面,你修改了?
  15. linux串口读取 GPS模块程序
  16. bat脚本的基本命令语法
  17. 【转】蛋糕尺寸(寸)、尺寸(CM)、重量(磅)、食用人数对照换算参考表...
  18. stm32f030烧录一次程序就不能检测到解决方法
  19. 用vlc搭建流媒体服务器
  20. Activity的理解

热门文章

  1. <choose>标签的使用
  2. nginx rtmp推流配置与测试
  3. IDEA插件下载地址
  4. Android获取明天日期
  5. 金山WPS c++ 一面面经
  6. 金山wps支持java接口开发吗_金山wps开放平台使用踩坑实录
  7. 改用Hamibot-艳云脚本云控系统
  8. ureport2报错/by zero的解决方法
  9. 工具类记录之Guawa的Splitter
  10. Vendor使用:golang的vendor是个啥?