C# - 反射与编译
编译
首先了解下,如何区分编译生成的 .dll的版本
方法1:ILSpy反编译工具
通过 assembly属性,release版本没有或仅有如下一种属性
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
而 debug版本,属性较多,示例
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations |
DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
具体参见:https://blog.csdn.net/WPwalter/article/details/80933080
方法2:代码检测
public static class Utils
{
//新增扩展方法
public static T GetCustomAttribute<T>(this ICustomAttributeProvider provider)
where T : Attribute
{
var attributes = provider.GetCustomAttributes(typeof(T), false);
return attributes.Length > 0 ? attributes[0] as T : default(T);
} public enum DllMode { Debug = 0, Release = 1 }; public static DllMode CheckDllMode_1(string _filePath)
{
var assembly = Assembly.LoadFile(_filePath);
var attributes = assembly.GetCustomAttributes(typeof(DebuggableAttribute), false);
if (attributes.Length > 0)
{
var debuggable = attributes[0] as DebuggableAttribute;
if (debuggable != null) {
return ((debuggable.DebuggingFlags & DebuggableAttribute.DebuggingModes.Default)
== DebuggableAttribute.DebuggingModes.Default)
? DllMode.Debug : DllMode.Release;
} else { return DllMode.Release; }
} else { return DllMode.Release; }
} public static DllMode CheckDllMode_2(string _filePath)
{
Assembly ass = Assembly.LoadFile(_filePath);
DebuggableAttribute att = ass.GetCustomAttribute<DebuggableAttribute>();
return (att != null && att.IsJITTrackingEnabled) ? DllMode.Debug : DllMode.Release;
} }
具体参见:https://www.oschina.net/code/snippet_12_8459
新增扩展方法时,若提示: 缺少编译器要求的成员“system.Runtime.CompilerServices.ExtensionAttribute..ctor”
解决方法,在当前.cs中添加
namespace System.Runtime.CompilerServices {
public class ExtensionAttribute : Attribute { }
}
反射
类Assembly中Load, LoadFrom, LoadFile方法比较
- http://www.cnblogs.com/liuzhendong/archive/2011/08/15/2139506.html
- http://www.cnblogs.com/xuqingfeng/archive/2012/05/22/assembly-load-loadfrom-loadfile-details.html
下面给出2种程序集加载方法
//方法1:直接从DLL路径加载 ok
assembly = Assembly.LoadFrom(assemblyPath); //方法2:先把DLL加载到内存,再从内存中加载 ok
using (FileStream fs = new FileStream(assemblyPath, FileMode.Open, FileAccess.Read))
{
using (BinaryReader br = new BinaryReader(fs))
{
byte[] bFile = br.ReadBytes((int)fs.Length);
br.Close();
fs.Close();
assembly = Assembly.Load(bFile);
}
}
可以将程序集中定义的所有类型暂存备用,调用时指定程序集和方法名即可
// htTypes是Hashtable
foreach (Type tp in assembly.GetTypes()) {
htTypes.Add(tp.Name, tp);
} string className = "Calculator.Calculator"; //程序集.类名
string funName = "Add"; //方法名
if (TypeTest.htTypes.ContainsKey(className))
{
var tp = (Type)TypeTest.htTypes[className];
var func = tp.GetMethod(funName);
if (null != func)
{
func.Invoke(null, new object[] { ... });
}
}
对于设置或获取字段或属性的值,注意区分静态/非静态
非静态的实例字段或属性,GetValue和SetValue时,第一个参数务必传入实例对象
object obj = Activator.CreateInstance(type, true);
而静态的,直接送null即可。设置时,保险起见可以作类型转换
var v = Convert.ChangeType(value, tp.GetField/GetProperty(_name).FieldType/PropertyType);
注,待加载的程序集可以在配置文件中配置。
<configSections>
<section name="assembly" type="System.Configuration.NameValueSectionHandler"/>
</configSections> <!-- key为程序集名称,value表示是否要加载 -->
<assembly>
<add key="Calculator.dll" value="1"/>
<add key="crudHelper.dll" value="1"/>
</assembly>
代码中动态加载即可
NameValueCollection assemblyList = ConfigurationManager.GetSection("assembly") as NameValueCollection;
.Net框架提供了一个综合性方法:Type.InvokeMember,但是参数较多,慎用。
应用
[1]. 获取当前执行的方法的信息:2种
MethodBase method = MethodBase.GetCurrentMethod();
string tag = method.ReflectedType.FullName + "." + method.Name; //类名.方法名 StackTrace stackTrace = new StackTrace(true);
MethodBase method = stackTrace.GetFrame(0).GetMethod();
string codeDestination = method.DeclaringType.Name + "-" + method.Name; //类名.方法名
若要获取父方法的信息,使用 GetFrame(1) 即可。
[2]. 提取类实例字段名和字段值
public static string GetAllKeyValue<T>(T t, IDictionary<string, object> dic, bool removeEmptyVal)
{
if (t == null || dic == null) { return "t||dic null"; } try {
System.Reflection.PropertyInfo[] properties = t.GetType().GetProperties(
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public);
if (properties.Length <= 0) { return "properties 0"; } foreach (System.Reflection.PropertyInfo item in properties) {
string name = item.Name;
object value = item.GetValue(t, null); if (item.PropertyType.IsValueType || item.PropertyType.Name.StartsWith("String")) {
if (removeEmptyVal && (value == null ||
(value is string && string.IsNullOrWhiteSpace(value.ToString())))) { /* not save empty value */ }
else { dic.Add(name, value); }
} else {
GetAllKeyValue(value, dic, removeEmptyVal);
}
}
} catch (Exception ex) {
return ex.Message + "||" + ex.StackTrace;
}
return string.Empty;
}
其中GetProperties()中的参数可以按需控制。
C# - 反射与编译的更多相关文章
- Java学习:注解,反射,动态编译
狂神声明 : 文章均为自己的学习笔记 , 转载一定注明出处 ; 编辑不易 , 防君子不防小人~共勉 ! Java学习:注解,反射,动态编译 Annotation 注解 什么是注解 ? Annotat ...
- 【UE4】基础概念——文件结构、类型、反射、编译、接口、垃圾回收、序列化
新标签打开或者下载看大图 思维导图 Engine Structure Pipeline Programming Pipeline Blueprint Pipeline
- 初识Scala反射
我们知道,scala编译器会将scala代码编译成JVM字节码,编译过程中会擦除scala特有的一些类型信息,在scala-2.10以前,只能在scala中利用java的反射机制,但是通过java反射 ...
- Java中的反射和注解
前言 在Java中,反射机制和注解机制一直是一个很重要的概念,那么他们其中的原理是怎么样呢,我们不仅仅需要会使用,更要知其然而之所以然. 目录 反射机制 反射如何使用 注解定义 注解机制原理 注解如何 ...
- 【C#进阶系列】23 程序集加载和反射
程序集加载 程序集加载,CLR使用System.Reflection.Assembly.Load静态方法,当然这个方法我们自己也可以显式调用. 还有一个Assembly.LoadFrom方法加载指定路 ...
- java 面向对象编程-- 第十三章 反射、类加载与垃圾回收
1.狭义JavaBean规范 Javabean必须包含一个无参数的public构造方法,方便通过反射的方式产生对象. 属性必须都是私有的. Javabean必须包含符合命名规范的get和set方法,以 ...
- 浅说Java中的反射机制(二)
写过一篇Java中的反射机制,不算是写,应该是抄了,因为那是别人写的,这一篇也是别人写的,摘抄如下: 引自于Java基础--反射机制的知识点梳理,作者醉眼识朦胧.(()为我手记) 什么是反射? 正常编 ...
- 初识Java反射
要详细的了解Java反射,就得要了解Java的类加载以及何为运行时动态加载等等概念.本文抛开其余概念,简单介绍Java反射,详细介绍会在以后有一个系统而全面的认识过后展开. 反射是Java被视为动态语 ...
- .NET Core单文件发布静态编译AOT CoreRT
.NET Core单文件发布静态编译AOT CoreRT,将.NET Core应用打包成一个可执行文件并包含运行时. 支持Windows, MacOS and Linux x64 w/ RyuJIT ...
随机推荐
- li.active2有加强重要性的效果。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- $.post 提示错误: Uncaught SyntaxError: Unexpected token :
$.post("addRecommond",{"productId":productId,"categoryCode":categoryCo ...
- classification report 使用
别人写的,但是还是有些不清晰,我最后补上了 最后一行:第一个0.7=(0.5*1+0*1+1*3)/5 其他类似 support行:在真实数据中y_ture中class 0有一个 class 1有1 ...
- 2018.09.29 bzoj3039: 玉蟾宫(悬线法)
传送门 悬线法的板子题. 悬线法只需要保存当期点向下最多多少个,把这个当成一条线,再处理出线绷直之后最多能向左右延展多少就行了. 代码: #include<bits/stdc++.h> # ...
- 2018.09.27 codeforces618F. Double Knapsack(抽屉原理+构造)
传送门 思维题. 考虑维护两个数列的前缀和a1,a2,a3,...,ana_1,a_2,a_3,...,a_na1,a2,a3,...,an和b1,b2,b3,...,bnb_1,b_2,b_ ...
- 2018.08.29 NOIP模拟 movie(状压dp/随机化贪心)
[描述] 小石头喜欢看电影,选择有 N 部电影可供选择,每一部电影会在一天的不同时段播 放.他希望连续看 L 分钟的电影.因为电影院是他家开的,所以他可以在一部电影播放过程中任何时间进入或退出,当然他 ...
- 《C++ Primer (V4)》读书笔记
第2章 变量和基本类型 1.(P56)如果使用class关键字来定义类,那么定义在第一个访问标号前的任何成员都隐式指定为private:如果使用struct关键字,那么这些成员都是public. 第7 ...
- linux安装mysql~~~mysql5.6.12
Linux安装mysql服务器 准备: MySQL-client-5.6.12-1.rhel5.i386.rpm MySQL-server-5.6.12-1.rhel5.i386.rpm 首先检查环境 ...
- where /group by/ having/ order by/
1.order by 是 按字段 进行排序.. 字段后面可跟 desc 降序..asc 升序..默认为升序2.group by 是进行分组 查询3.having 和 where 都属于 条件过滤 区别 ...
- 聚合函数、group by
聚合函数: sql语言中一种特殊的函数:聚合函数,SUM, COUNT, MAX, MIN, AVG等.这些函数和其它函数的根本区别就是它们一般作用在多条记录上.SELECT SUM(populati ...