做这个功能目的是对旧项目代码分析管理,代码规划。

  如果重头开发,统一一个框架小框架搞,人、时间到位都不是问题。但是旧应用系统优化,项目更新,就几个人开发加维护,接口层越多,bll层越来越厚,人来人往留下一堆代码,怎么管理呢?我现在方法是:看,仔细看,再仔细看,改,仔细改,再仔细改。一般出问题了,结合数据库,基本可以解决。如果重新搞,还得熟悉原来的代码,再搬进新的项目,费时费力。有没有一种方式最好不用写代码,做个配置界面,将业务SQL和逻辑用工作流的方式以字符串(JSon、描述对象模型(这玩意我自定义了一个对象来描述各类关系,下次讲))的形式先保存起来,形成一个运行时编程环境,配置完善后通过字符串生成自己喜欢的框架呢?找了好久没找到,就自己写个。

  要解决不要写代码,那么所有层的Model(实体、DTO、其他业务模型)肯定要用运行时模型,传输统一用字符串,哪一层都能接受。这样一想,思路就有了。这里的所有模型只做三个事情:实例化、输入和输出。输入为object或者json,输出为object或者dynamic也可以是JSon。代码做了简单的封装。直接上代码:

动态生成帮助类:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Reflection;
  5 using System.Reflection.Emit;
  6 using System.Text;
  7 using System.Threading.Tasks;
  8
  9 namespace MagicModel
 10 {
 11     public abstract  class EmitHelper
 12     {
 13
 14         private static AssemblyName assmblyname;
 15         private static string DllName;
 16         private static AssemblyBuilder assemblybuilder;
 17         private static ModuleBuilder modulebuilder;
 18         private static TypeBuilder typebuilder;
 19         private static Type _dymaticType;
 20
 21         public static Type DymaticType
 22         {
 23             get
 24             {
 25                 return _dymaticType;
 26             }
 27
 28             //set
 29             //{
 30             //    dymaticType = value;
 31             //}
 32         }
 33
 34         public static void Create(string dllname)
 35         {
 36             DllName = dllname;
 37             assmblyname = new AssemblyName(DllName);
 38             ///2程序集生成器
 39             assemblybuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assmblyname, AssemblyBuilderAccess.RunAndSave);
 40
 41             // For a single-module assembly, the module name is usually
 42             // the assembly name plus an extension.
 43             ////3动态创建模块
 44             modulebuilder = assemblybuilder.DefineDynamicModule(assmblyname.Name, assmblyname.Name + ".dll");
 45         }
 46         public static void CreateClass(string NsClassName)
 47         {
 48             typebuilder = modulebuilder.DefineType(NsClassName, TypeAttributes.Public);
 49         }
 50         public static void CreateMember(string MemberName, Type memberType)
 51         {
 52             FieldBuilder fbNumber = typebuilder.DefineField(
 53               "m_" + MemberName,
 54              memberType,
 55               FieldAttributes.Private);
 56
 57
 58             PropertyBuilder pbNumber = typebuilder.DefineProperty(
 59                 MemberName,
 60                 System.Reflection.PropertyAttributes.HasDefault,
 61                 memberType,
 62                 null);
 63
 64
 65             MethodAttributes getSetAttr = MethodAttributes.Public |
 66                 MethodAttributes.SpecialName | MethodAttributes.HideBySig;
 67
 68
 69             MethodBuilder mbNumberGetAccessor = typebuilder.DefineMethod(
 70                 "get_" + MemberName,
 71                 getSetAttr,
 72                 memberType,
 73                 Type.EmptyTypes);
 74
 75             ILGenerator numberGetIL = mbNumberGetAccessor.GetILGenerator();
 76
 77             numberGetIL.Emit(OpCodes.Ldarg_0);
 78             numberGetIL.Emit(OpCodes.Ldfld, fbNumber);
 79             numberGetIL.Emit(OpCodes.Ret);
 80
 81             // Define the "set" accessor method for Number, which has no return
 82             // type and takes one argument of type int (Int32).
 83             MethodBuilder mbNumberSetAccessor = typebuilder.DefineMethod(
 84                 "set_" + MemberName,
 85                 getSetAttr,
 86                 null,
 87                 new Type[] { memberType });
 88
 89             ILGenerator numberSetIL = mbNumberSetAccessor.GetILGenerator();
 90             // Load the instance and then the numeric argument, then store the
 91             // argument in the field.
 92             numberSetIL.Emit(OpCodes.Ldarg_0);
 93             numberSetIL.Emit(OpCodes.Ldarg_1);
 94             numberSetIL.Emit(OpCodes.Stfld, fbNumber);
 95             numberSetIL.Emit(OpCodes.Ret);
 96
 97             // Last, map the "get" and "set" accessor methods to the
 98             // PropertyBuilder. The property is now complete.
 99             pbNumber.SetGetMethod(mbNumberGetAccessor);
100             pbNumber.SetSetMethod(mbNumberSetAccessor);
101             ///最重要的是你最后要创建类型
102
103         }
104         public static Type SaveClass()
105         {
106             _dymaticType = typebuilder.CreateType();
107             return DymaticType;
108         }
109         public static void Save()
110         {
111             assemblybuilder.Save(assmblyname.Name + ".dll");
112         }
113         ///// <summary>
114         ///// 创建一个实体类并保存生成类型
115         ///// </summary>
116         ///// <param name="NsClassName"></param>
117         ///// <param name="propertys"></param>
118         //public void Execute(string NsClassName, Dictionary<string, Type> propertys)
119         //{
120
121         //    CreateClass(NsClassName);
122         //    foreach (var item in propertys)
123         //    {
124         //        CreateMember(item.Key, item.Value);
125         //    }
126         //    SaveClass();
127         //    Save();
128         //}
129
130         //public void Execute(List<M_DefineClass> _classes) {
131
132         //    foreach (M_DefineClass _class in _classes)
133         //    {
134         //        CreateClass(_class.NsClassName);
135         //        foreach (var prop in _class.Props)
136         //        {
137         //            CreateMember(prop.MemberName, prop.MemberType);
138         //        }
139         //        SaveClass();
140         //    }
141
142         //}
143
144         //public void Test(string dllname, string NsClassName, string MemberName, Type memberType)
145         //{
146         //    //1设置程序集名称
147         //    assmblyname = new AssemblyName(dllname);
148         //    ///2程序集生成器
149         //    assemblybuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assmblyname, AssemblyBuilderAccess.RunAndSave);
150         //    3动态创建模块
151         //    modulebuilder = assemblybuilder.DefineDynamicModule(assmblyname.Name, assmblyname.Name + ".dll");
152         //    ///4.创建类
153         //    typebuilder = modulebuilder.DefineType(NsClassName, TypeAttributes.Public);
154         //    ///5.创建私有字段
155         //    FieldBuilder fbNumber = typebuilder.DefineField(
156         //     "m_" + MemberName,
157         //     memberType,
158         //     FieldAttributes.Private);
159
160         //    ///6.创建共有属性
161         //    PropertyBuilder pbNumber = typebuilder.DefineProperty(
162         //        MemberName,
163         //        System.Reflection.PropertyAttributes.HasDefault,
164         //        memberType,
165         //        null);
166
167
168         //    MethodAttributes getSetAttr = MethodAttributes.Public |
169         //        MethodAttributes.SpecialName | MethodAttributes.HideBySig;
170
171
172         //    MethodBuilder mbNumberGetAccessor = typebuilder.DefineMethod(
173         //        "get_" + MemberName,
174         //        getSetAttr,
175         //        memberType,
176         //        Type.EmptyTypes);
177
178         //    ILGenerator numberGetIL = mbNumberGetAccessor.GetILGenerator();
179
180         //    numberGetIL.Emit(OpCodes.Ldarg_0);
181         //    numberGetIL.Emit(OpCodes.Ldfld, fbNumber);
182         //    numberGetIL.Emit(OpCodes.Ret);
183
184         //    // Define the "set" accessor method for Number, which has no return
185         //    // type and takes one argument of type int (Int32).
186         //    MethodBuilder mbNumberSetAccessor = typebuilder.DefineMethod(
187         //        "set_" + MemberName,
188         //        getSetAttr,
189         //        null,
190         //        new Type[] { typeof(int) });
191
192         //    ILGenerator numberSetIL = mbNumberSetAccessor.GetILGenerator();
193         //    // Load the instance and then the numeric argument, then store the
194         //    // argument in the field.
195         //    numberSetIL.Emit(OpCodes.Ldarg_0);
196         //    numberSetIL.Emit(OpCodes.Ldarg_1);
197         //    numberSetIL.Emit(OpCodes.Stfld, fbNumber);
198         //    numberSetIL.Emit(OpCodes.Ret);
199
200         //    // Last, map the "get" and "set" accessor methods to the
201         //    // PropertyBuilder. The property is now complete.
202         //    pbNumber.SetGetMethod(mbNumberGetAccessor);
203         //    pbNumber.SetSetMethod(mbNumberSetAccessor);
204
205         //    ///最重要的是你最后要创建类型
206         //    Type t = typebuilder.CreateType();
207         //    assemblybuilder.Save(assmblyname.Name + ".dll");
208
209         //}
210
211
212     }
213 }

View Code

初始动态模型:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace MagicModel.BLL
{public class DynamicInitBLL{static M_Base _m_base;/// <summary>/// 3.设置和获取,生成结果放入Base里/// </summary>public static M_Base M_Base{get{return _m_base;}set{_m_base = value;}}/// <summary>/// 初始化,实现步骤为三步/// </summary>/// <param name="m_base"></param>public DynamicInitBLL(M_Base m_base) {_m_base = m_base;EmitHelper.Create(_m_base._AssamblyName);}/// <summary>/// 1创建单个Class/// </summary>/// <param name="_class"></param>public void Exequte(M_DefineClass _class){EmitHelper.CreateClass(_class.NsClassName);foreach (var prop in _class.Props){EmitHelper.CreateMember(prop.MemberName, prop.MemberType);}_m_base.DymaticType.Add(new M_DymaticType() {TypeName=_class.NsClassName,DType= EmitHelper.SaveClass() });}/// <summary>/// 1创建多个Class/// </summary>/// <param name="_classes"></param>public void Exequte(List<M_DefineClass> _classes) {foreach (var item in _classes){Exequte(item);}}/// <summary>/// 2保存/// </summary>public void SaveAssembly() {EmitHelper.Save();}}
}

View Code

模型赋值:

using MagicModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;namespace MagicModel.BLL
{public class DynamicEmulateBLL{M_Base _m_base;public DynamicEmulateBLL(M_Base _mbase) {_m_base = _mbase;}public object ObjectEmulate(string nsclassName,object data) {Type _classType = _m_base.DymaticType.Where(a => a.TypeName == nsclassName).FirstOrDefault().DType;var obj = Activator.CreateInstance(_classType);foreach (PropertyInfo pi in _classType.GetProperties()){if (data.GetType().GetProperty(pi.Name)!=null){Console.WriteLine("有相同的值");pi.SetValue(obj, data.GetType().GetProperty(pi.Name).GetValue(data));} }return obj;}public object JsonEmulate(string nsclassName, string jsonstring) {Type _classType = _m_base.DymaticType.Where(a => a.TypeName == nsclassName).FirstOrDefault().DType;return    Newtonsoft.Json.JsonConvert.DeserializeObject(jsonstring, _classType);}}
}

View Code

交互模型:

using System;
using System.Collections.Generic;namespace MagicModel
{public class M_Base {public string _AssamblyName { get; set; }public List<M_DymaticType> DymaticType { get; set; } = new List<M_DymaticType>();}public class M_DymaticType{public string TypeName { get; set; }public Type DType { get; set; }}public class M_DefineClass{public string NsClassName { get;  set; }public IEnumerable<M_ClassMember> Props { get;  set; }}public class M_ClassMember {public string MemberName { get;  set; }public Type MemberType { get;  set; }}}

View Code

下面来测试下效果,先定义10个类:

打开vs里面的cmd开发人员命令提示”,输入ildasm,然后把生成的dll拖进去,有了。

赋值检验:

有效果了

  到了这一步,动态模型生成完成,它的调用位置不仅限于运行时代码,也可以在其他环境中使用了。

  疑问:

  1.运行时环境下处理引用问题是个麻烦事,所以干脆静态一个AssemblyName,项目间交叉引用该怎么解决?

2.我开始用Assembly去取dll,发现两个问题。1,交叉引用出问题。2,赋值取值出问题。

3.这个RunAndSave参数直接加载进来了,所以就在这上面static保存在内存等待以后调用,有没有更好的方法调用?或者说我生成的dll文件想什么时候用什么时候用,在哪里用都由我决定。

以上资料全参考msdn。

模型层可以存库,做生成对比,做db对比等等,后面再优化!

转载于:https://www.cnblogs.com/coolbader/p/7959650.html

使用Emit反射建立运行时模型相关推荐

  1. 使用Emit反射建立运行时实体模型

    做这个功能目的是对旧项目代码分析管理,代码规划. 如果重头开发,统一一个框架小框架搞,人.时间到位都不是问题.但是旧应用系统优化,项目更新,就几个人开发加维护,接口层越多,bll层越来越厚,人来人往留 ...

  2. jvm优化_镜像镜像–使用反射在运行时查看JVM内部

    jvm优化 开发人员:Takipi会告诉您何时新代码在生产中中断–了解更多 我们都习惯于在我们的日常工作中直接或通过利用反射的框架来运用反射. 它是Java和Scala编程的主要方面,它使我们使用的库 ...

  3. jvm 内存镜像_镜像镜像–使用反射在运行时查看JVM内部

    jvm 内存镜像 开发人员:Takipi会告诉您何时新代码在生产中中断– 了解更多 我们都习惯于在我们的日常工作中直接或通过利用反射的框架来运用反射. 它是Java和Scala编程的主要方面,它使我们 ...

  4. 镜像镜像–使用反射在运行时查看JVM内部

    开发人员:Takipi会告诉您何时新代码在生产中中断– 了解更多 我们都习惯于在我们的日常工作中直接或通过利用反射的框架来运用反射. 它是Java和Scala编程的主要方面,它使我们使用的库可以与我们 ...

  5. Java反射运行时_java反射获得运行时属性的值

    运行时动态获得属性的值(通过方法获得): Method[] methods = cls.getDeclaredMethods(); for (Method method : methods) { if ...

  6. 通过反射--操作运行时类中的指定的属性/方法

    操作运行时类中的指定的属性: 1.getDeclaredField(String fieldName):获取运行类中指定变量名的属性: 2.保证当前属性时可访问的 : 属性.setAccessible ...

  7. Java基础知识点__获取运行时类的完整结构

    通过反射获取运行时类的完整结构 Field,method,Construuuctor,Superclass,Interface,Annotation 实现的全部接口 继承的父类 全部的构造器 全部的构 ...

  8. @JVM内存模型(运行时数据区)

    前言 说到Java内存区域,可能很多人第一反应是"堆栈".首先堆栈不是一个概念,而是两个概念,堆和栈是两块不同的内存区域,简单理解的话,堆是用来存放对象而栈是用来执行程序的.对于J ...

  9. JDK1.8-Java虚拟机运行时数据区域和HotSpot虚拟机的内存模型

    2019独角兽企业重金招聘Python工程师标准>>> 官方文档规定的运行时数据区域 官方文档中规定的运行时数据区一共就几块: PC计数器, 虚拟机栈, 本地方法栈, 堆区, 方法区 ...

  10. JVM 内存模型:运行时常量池

    1. 前言 最近研究Java基础知识.发现Java运行时常量池和String字符串有些一些细节的地方,值得我们注意的地方,最为一个Java开发人员对于这种java基本特性和JVM虚拟机的内存模型我们需 ...

最新文章

  1. hadoop实战二 单机部署2
  2. 电子书推荐--《Python灰帽子》,python黑客编程
  3. Python入门学习笔记11(静态方法、类方法与属性方法)
  4. 有一种叫“蒸汽波”豪横的平面设计手法
  5. 最长上升子序列LIS 动态规划 二分查找算法
  6. 类似pyinstaller_pyinstaller安装与使用——那些我踩过的坑
  7. nginx php mysql zend_性能测试基本功 - 手动配置nginx+php-cgi+zend+mysql
  8. 如何用Java实现进度条
  9. 计算机无法识别荣耀9,华为荣耀9连接不上电脑端华为手机助手怎么处理?
  10. CT图像去除金属伪影-MATLAB实现
  11. 统计检验方法 大全,t -test 检验,Anova 检验,卡方检验,Kolmogorov–Smirnov 检验
  12. 力扣刷题(347. 前 K 个高频元素)快速排序
  13. iPad播放网页视频(h5 video)失败的处理方法(Django网站)
  14. 有时候可用 UIWebView 代替 UITextView,解决行间距问题
  15. mysql sus bench_susbench性能测试工具
  16. ChinaSkills-高职组网络系统管理大赛-WinSer 2019 互联网网卡检测服务笔记
  17. QQ强制加好友链接,对方不同意我也加
  18. 双系统安装红旗linux,红旗LINUX怎么安装成双系统?
  19. 【点云系列】基于图结构的点云快速重采样 翻译
  20. Ventoy - 免格式化!超简单的『多合一』系统启动盘制作神器 (开源免费,多平台支持)...

热门文章

  1. 邮件服务器搬家,企业邮箱怎么“搬家”
  2. 访问HDFS报错:org.apache.hadoop.security.AccessControlException: Permission denied
  3. Ubuntu16.x服务器 安装 Java,Elasticsearch5.4.X,中文分词,同义词,Logstash5.4.X 日志搜集
  4. Win 10 下载与安装 Oracle 12c 详细图解 与 Oracle 12c 卸载
  5. Java 设计模式 之 单例模式(Singleton)
  6. 小马哥-Java 微服务实践 - Spring Boot 系列-01Java 微服务实践 - Spring Boot 系列(一)初体验...
  7. 小D课堂 - 零基础入门SpringBoot2.X到实战_第2节 SpringBoot接口Http协议开发实战_6、SpringBoot2.xHTTP请求配置讲解...
  8. ultraedit激活
  9. windbg分析Kernel32.dll导出表
  10. objective-C语言:第一个OC程序