编译
首先了解下,如何区分编译生成的 .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()中的参数可以按需控制。