.NET 反射的使用
1.根据类名获取类实例
string className = "Company.BigProgram.BLL.TestClass"; Type type = Type.GetType(className); if (type != null) { Object obj = Activator.CreateInstance(type); bool b = obj is TestClass; }
className是包含命名空间的类名
在这里只是根据类名创建了一个实例,但是没有将其转换为相应的实体类。所以一般情况 这里反射的类都应该有一个共同的接口(或者说有一个共同的父类);
这样就能很明确的创建和使用由反射得来的实体类了
//接口 namespace Company.BigProgram.BLL { public interface ITest { void say(string name); } }
//具体实现类 namespace Company.BigProgram.BLL { public class TestClass:ITest { public void say(string name) { Console.WriteLine("看这里"); } } }
//结果输出 string className = "ImageTest.TestClass"; Type type = Type.GetType(className); if (type != null) { ITest obj = Activator.CreateInstance(type) as ITest; bool b = obj is TestClass; MessageBox.Show(b.ToString());//True }
2.根据实例和其属性名(字符串) 获取该属性
/// <summary> /// 获取某个对象的某个属性值 /// </summary> /// <param name="type">对象</param> /// <param name="propName">属性名</param> /// <returns>属性值</returns> private string GetPropertyValue<T>(T item, string propName) { Type type = item.GetType();//获取类型 System.Reflection.PropertyInfo propertyInfo = type.GetProperty(propName); return (propertyInfo.GetValue(item, null) ?? "").ToString(); }
3.根据实例和其方法名(字符串)获取该方法并调用
private void GetPropertyValue<T>(T item, string name,object[] paras) { System.Type type = item.GetType();//获取类型 System.Reflection.MethodInfo func = type.GetMethod(name);//获取方法 func.Invoke(item, paras);//调用 item是调用该方法的对象,paras是参数 } private class Person { public void say() { MessageBox.Show("XXXXOOOO"); } public void call(string content) { MessageBox.Show(content); } }
上面三种Demo都是针对提前定义好的类型和方法属性。
下面是根据提供的字段信息动态编译的方法。
string colsStr = "Age,Name,Sex,Birthday";//字段名 string[] colNames = colsStr.Split(','); string clsName = "DynUserTable";//动态生成的类名 string ns = "MyWeb.Test";//命名空间 var propStr = ""; foreach (var c in colNames) { propStr += $" public string {c}{{set;get;}}\r\n"; } var typeStr = $@" namespace {ns} {{ public class {ns} {{ {propStr} }} }}";//拼接类的定义内容 //获取编译结果 var cr = new CSharpCodeProvider() .CompileAssemblyFromSource(new CompilerParameters(new string[] { "System.dll" }), typeStr); //获取类型 var targetType = cr.CompiledAssembly.GetType($"{ns}.{clsName}");
这里有一篇.NET动态编译的文章.NET中的动态编译
关于应用程序域AppDomain的使用 走近.NET AppDomain
说到动态编译 Emit效率更高,是通过C#直接生成IL,不过可读性较差
//动态创建程序集 AssemblyName DemoName = new AssemblyName("DynamicAssembly"); AssemblyBuilder dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(DemoName , AssemblyBuilderAccess.ReflectionOnly);//如果需要持久化程序集 则选择RunAndSave或Save //动态创建模块 ModuleBuilder mb = dynamicAssembly.DefineDynamicModule(DemoName.Name, DemoName.Name + ".dll"); //动态创建类MyClass TypeBuilder tb = mb.DefineType("MyClass", TypeAttributes.Public); //动态创建字段 FieldBuilder fb = tb.DefineField("myField", typeof(string), FieldAttributes.Private); //动态创建构造函数(一个参数) Type[] clorType = new Type[] { typeof(string) }; ConstructorBuilder cb1 = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, clorType); //生成 Microsoft 中间语言 (MSIL) 指令(将构造函数的参数赋给字段fb) ILGenerator ilg = cb1.GetILGenerator(); ilg.Emit(OpCodes.Ldarg_0); ilg.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); ilg.Emit(OpCodes.Ldarg_0); ilg.Emit(OpCodes.Ldarg_1); ilg.Emit(OpCodes.Stfld, fb); ilg.Emit(OpCodes.Ret); //动态创建属性 PropertyBuilder pb = tb.DefineProperty("MyProperty", PropertyAttributes.HasDefault, typeof(string), null); //动态创建方法 MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName; MethodBuilder myMethod = tb.DefineMethod("get_Field", getSetAttr, typeof(string), Type.EmptyTypes); //生成指令(方法返回fb) ILGenerator numberGetIL = myMethod.GetILGenerator(); numberGetIL.Emit(OpCodes.Ldarg_0); numberGetIL.Emit(OpCodes.Ldfld, fb); numberGetIL.Emit(OpCodes.Ret); //使用动态类创建类型 Type classType = tb.CreateType();
相关文章