• .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;}}
    ";
    }
    
    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();

    相关文章

    说说emit(上)基本操作


  • 相关阅读:
    python中类方法、类实例方法、静态方法的使用与区别
    在python里如何动态添加类的动态属性呢?
    PYTHON基础
    EXCEL 写入
    thread 多线程
    Python 常用函数
    列表减列表
    04_Linux搭建Jdk和tomcat环境
    自动生成和安装requirements.txt依赖
    python+selenium面试题
  • 原文地址:https://www.cnblogs.com/TiestoRay/p/2605485.html
Copyright © 2020-2023  润新知