首页 > 编程语言 >学习笔记:C#高级进阶语法——反射

学习笔记:C#高级进阶语法——反射

时间:2025-01-02 13:57:45浏览次数:1  
标签:进阶 C# Type GetType 语法 new type public string

二、反射(Reflection)

1、反射:就是一个微软提供的帮助类库,可以解析并使用元数据。

2、exe/dll----ILSpy工具打开会包含matedata(元数据),描述了当前程序集中有哪些元素成员

3、反射动态加载dll文件,调用方法

 {
     //1、引用,2、new,3、调方法
     IDBHelper helper = new SqlServerHelper();
     helper.Query();
 }
 {
     //反射方式:
     //1、动态加载dll文件
     Assembly assembly1 = Assembly.Load("Business.DB.SqlServer");//带上dll名称,在当前执行目录下找
     Assembly assembly2 = Assembly.LoadFrom("Business.DB.SqlServer.dll");//带上.dll后缀名,在当前执行目录下找
     Assembly assembly3 = Assembly.LoadFile("D:\\GIT\\Advanced\\Advanced" +
         "\\MyReflection\\Business.DB.SqlServer.dll");//带上全路径
     //2、获取类型名称
     Type type = assembly1.GetType("Business.DB.SqlServer.SqlServerHelper");
     //3、使用反射创建对象
     object? oInstance = Activator.CreateInstance(type);
     //4、类型转换
     IDBHelper helper = oInstance as IDBHelper;
     //5、调用方法
     helper.Query();

     dynamic oInstance1 = Activator.CreateInstance(type);
     oInstance1.Query();
     oInstance1.fasdfdsfqwe123412();//不存在的方法也可以写,不严谨的

     //在不知道dll档中有什么内容可以这样获取所有的
     //foreach (var type in assembly1.GetTypes())
     //{
     //    Console.WriteLine($"Type.Name={type.Name}");
     //    foreach (var item in type.GetMethods())
     //    {
     //        Console.WriteLine($"Method.Name={item.Name}");
     //    }
     //    foreach (var item in type.GetProperties())
     //    {
     //        Console.WriteLine($"Property.Name={item.Name}");
     //    }
     //    foreach (var item in type.GetProperties())
     //    {
     //        Console.WriteLine($"Property.Name={item.Name}");
     //    }
     //}
 }

4、反射+配置文件+简单工厂---实现程序的可配置化

应用:比如动态更新dll版本,比如数据库从SqlServer切换到Mysql

using Business.DB.Interface;
using Microsoft.Extensions.Configuration;
using System;
using System.Reflection;

namespace MyReflecttion
{
    public class SimpleFactory
    { 
        /// <summary>
        /// 提供一个返回IDBHelper的方法
        /// 1、完全断开了对于普通类的依赖
        /// 2、配置文件的修改,不需要停止项目运行
        /// 3、反射+配置文件+简单工厂===程序的可配置化, 可以扩展化~
        /// </summary>
        /// <returns></returns>
        public static IDBHelper CreateInstance()
        { 
            string ReflictionConfig = CustomConfigManager.GetConfig("ReflictionConfig");
            string[] strings= ReflictionConfig.Split(',');
            string dllName = strings[1];
            string typeName = strings[0]; 
            Assembly assembly = Assembly.LoadFrom(dllName);  
            Type type = assembly.GetType(typeName);  
            object? oInstance = Activator.CreateInstance(type); 
            IDBHelper dBHelper = oInstance as IDBHelper; 
            return dBHelper; 
        }
    }

     
    public static class CustomConfigManager
    { 
        //Core 读取配置文件:appsettings
        //1.Microsoft.Extensions.Configuration;
        //2.Microsoft.Extensions.Configuration.Json 
        public static string GetConfig(string key)
        {
            var builder = new ConfigurationBuilder().AddJsonFile("appsettings.json");  //默认读取  当前运行目录
            IConfigurationRoot configuration = builder.Build();
            string configValue = configuration.GetSection(key).Value;
            return configValue;
        }
    }
}

5、反射黑科技:反射破坏单例,反射可以突破访问修饰符的权限(比如Private私有修饰,可以在类外部调用)

//定义一个单例,构造函数定义为私有的,在类的外部可以调用它。
namespace DB.SqlServer
{
    public sealed class Singleton
    {
        private static Singleton _Singleton;

        private Singleton()
        {
            Console.WriteLine("构造函数被调用");
        }

        static Singleton()
        {
            _Singleton = new Singleton();
        }

        public static Singleton GetInstance() { return _Singleton; }
    }
}

6、反射调用方法+反射创建对象升级

​ 1、获取要调用的方法名称

​ 2、获取方法的类型,MethodInfo

​ 3、Invoke方法,执行方法

{
    //调用普通方法
    Assembly assembly = Assembly.LoadFrom("DB.SqlServer.dll");
    Type? type = assembly.GetType("DB.SqlServer.SqlServerHelper");
    object? oInstance = Activator.CreateInstance(type);
    MethodInfo query = type.GetMethod("Query");
    query.Invoke(oInstance, new object[0]);
}
{
    //在反射创建对象的时候,如何指定执行多个构造函数中的某个?
    Assembly assembly = Assembly.LoadFrom("DB.SqlServer.dll");
    Type? type = assembly.GetType("DB.SqlServer.ReflectionTest");
    //如果要选择构造函数,在调用方法的时候,直接传入和参数列表匹配的参数即可
    object? oInstance = Activator.CreateInstance(type);
    object? oInstance1 = Activator.CreateInstance(type,new object[] {"你好" });
    object? oInstance2 = Activator.CreateInstance(type,new object[] { 1233});
    object? oInstance3 = Activator.CreateInstance(type,new object[] { "你好",123});
    object? oInstance4 = Activator.CreateInstance(type,new object[] { 123,"你好不好"});
}

{
    //执行各种方法
    Assembly assembly = Assembly.LoadFrom("DB.SqlServer.dll");
    Type? type = assembly.GetType("DB.SqlServer.SqlServerHelper");
    object? oInstance = Activator.CreateInstance(type);
    //执行Show1  --无参方法
    MethodInfo query = type.GetMethod("Show1");
    query.Invoke(oInstance, null);
    //执行Show2  --带参方法
    MethodInfo query2 = type.GetMethod("Show2");
    query.Invoke(oInstance, [3456]);//传入的参数类型要和方法的参数完全匹配
    //执行Show3 --重载方法
    //对于重载方法,需要进一步精确查找的是哪个方法
    MethodInfo query3 = type.GetMethod("Show3",new Type[] { typeof(int),typeof(string)});
    query.Invoke(oInstance, new object[] { 123412,"你好我不好"});
    //执行Show4  --私有方法
    MethodInfo query4 = type.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic);
    query4.Invoke(oInstance, new object[] { "你好我不好" });
    //执行Show5  --静态方法
    MethodInfo query5 = type.GetMethod("Show4");
    query5.Invoke(null, new object[] { "你好我不好" });//静态类不需要类的实例就可以执行
}
//测试类如下
namespace DB.SqlServer
{
    /// <summary>
    /// 反射测试类
    /// </summary>
    public class ReflectionTest
    {
        #region Identity
        /// <summary>
        /// 无参构造函数
        /// </summary>
        public ReflectionTest()
        {

            Console.WriteLine($"这里是{GetType()}无参数构造函数");
        }

        /// <summary>
        /// 带参数构造函数
        /// </summary>
        /// <param name="name"></param>
        public ReflectionTest(string name)
        {
            Console.WriteLine($"这里是{GetType()} 有参数构造函数");
        }

        public ReflectionTest(int id)
        {
            Console.WriteLine($"这里是{GetType()} 有参数构造函数");
        }

        public ReflectionTest(int id, string name)
        {

            //typeof(int);

            //Type //id.GetType();

            Console.WriteLine($"这里是{GetType()} 有参数构造函数");
        }

        public ReflectionTest(string name, int id)
        {

            //typeof(int);

            //Type //id.GetType();

            Console.WriteLine($"这里是{GetType()} 有参数构造函数");
        }

        #endregion

        #region Method
        /// <summary>
        /// 无参方法
        /// </summary>
        public void Show1()
        {
            Console.WriteLine($"这里是{GetType()}的Show1");
        }
        /// <summary>
        /// 有参数方法
        /// </summary>
        /// <param name="id"></param>
        public void Show2(int id)
        {

            Console.WriteLine($"这里是{GetType()}的Show2");
        }
        /// <summary>
        /// 重载方法之一
        /// </summary>
        /// <param name="id"></param>
        /// <param name="name"></param>
        public void Show3(int id, string name)
        {
            Console.WriteLine($"这里是{GetType()}的Show3");
        }
        /// <summary>
        /// 重载方法之二
        /// </summary>
        /// <param name="name"></param>
        /// <param name="id"></param>
        public void Show3(string name, int id)
        {
            Console.WriteLine($"这里是{GetType()}的Show3_2");
        }
        /// <summary>
        /// 重载方法之三
        /// </summary>
        /// <param name="id"></param>
        public void Show3(int id)
        {

            Console.WriteLine($"这里是{GetType()}的Show3_3");
        }
        /// <summary>
        /// 重载方法之四
        /// </summary>
        /// <param name="name"></param>
        public void Show3(string name)
        {

            Console.WriteLine("这里是{this.GetType()}的Show3_4");
        }
        /// <summary>
        /// 重载方法之五
        /// </summary>
        public void Show3()
        {

            Console.WriteLine($"这里是{GetType()}的Show3_1");
        }
        /// <summary>
        /// 私有方法
        /// </summary>
        /// <param name="name"></param>
        private void Show4(string name)  //肯定是可以的
        {
            Console.WriteLine($"这里是{GetType()}的Show4");
        }
        /// <summary>
        /// 静态方法
        /// </summary>
        /// <param name="name"></param>
        public static void Show5(string name)
        {
            Console.WriteLine($"这里是{typeof(ReflectionTest)}的Show5");
        }
        #endregion
    }
}

7、泛型类、泛型方法调用

{
    //普通类的泛型方法调用
    Assembly assembly = Assembly.LoadFrom("DB.SqlServer.dll");
    Type type = assembly.GetType("DB.SqlServer.GenericMethod");
    object? oInstance = Activator.CreateInstance(type);
    MethodInfo show = type.GetMethod("Show");
    MethodInfo generic = show.MakeGenericMethod(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
    generic.Invoke(oInstance,new object[] { 123,"1234",DateTime.Now});
}
{
    //泛型类的普通方法调用
    Assembly assembly = Assembly.LoadFrom("DB.SqlServer.dll");
    Type type = assembly.GetType("DB.SqlServer.GenericClass`3");
    Type typeG = type.MakeGenericType(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
    object? oInstance = Activator.CreateInstance(typeG);
    MethodInfo show = typeG.GetMethod("Show");
    show.Invoke(oInstance, new object[] { 123, "1234", DateTime.Now });
}
{
    //泛型类的泛型方法调用
    Assembly assembly = Assembly.LoadFrom("DB.SqlServer.dll");
    Type type = assembly.GetType("DB.SqlServer.GenericDouble`1");
    Type typeG = type.MakeGenericType(new Type[] { typeof(int) });
    object? oInstance = Activator.CreateInstance(typeG);
    MethodInfo show = typeG.GetMethod("Show");
    MethodInfo generic = show.MakeGenericMethod(new Type[] { typeof(string), typeof(DateTime) });
    generic.Invoke(oInstance, new object[] { 123, "1234", DateTime.Now });
}
//测试类如下
namespace DB.SqlServer
{
    public class GenericMethod
    {
        public void Show<T, W, X>(T t, W w, X x)
        {
            Console.WriteLine($"t.type={t.GetType().Name},w.type={w.GetType().Name},x.type={x.GetType().Name}");
            Console.WriteLine($"T={t},W={w},X={x}");
        }
    }

    public class GenericClass<T, W, X>
    {
        public void Show(T t, W w, X x)
        {
            Console.WriteLine($"t.type={t.GetType().Name},w.type={w.GetType().Name},x.type={x.GetType().Name}");
        }
    }

    public class GenericDouble<T>
    {
        public void Show<W, X>(T t, W w, X x)
        {
            Console.WriteLine($"t.type={t.GetType().Name},w.type={w.GetType().Name},x.type={x.GetType().Name}");
        }
    }
}

8、反射的局限性---性能问题

反射方式比普通方式的耗时,高一倍以上。

反射不否认他有性能损失,但是只要程序员足够优秀,性能是可以得到优化的,可以放心使用

using DB.Interface;
using DB.SqlServer;
using System.Diagnostics;
using System.Reflection;

namespace MyReflection
{
    public class Monitor
    {
        public static void Show()
        {
            Console.WriteLine("*******************Monitor*******************");
            long commonTime = 0;
            long reflectionTime = 0;
            {
                Stopwatch watch = new Stopwatch();
                watch.Start();
                for (int i = 0; i < 1000_000; i++) //1000000000
                {
                    IDBHelper iDBHelper = new SqlServerHelper();
                    iDBHelper.Query();
                }
                watch.Stop();
                commonTime = watch.ElapsedMilliseconds;
            }
            {
                Stopwatch watch = new Stopwatch();
                watch.Start();

                Assembly assembly = Assembly.LoadFrom("DB.SqlServer.dll");//1 动态加载
                Type dbHelperType = assembly.GetType("DB.SqlServer.SqlServerHelper");//2 获取类型
                for (int i = 0; i < 1000_000; i++)
                {
                    //Assembly assembly = Assembly.LoadFrom("DB.SqlServer.dll");//1 动态加载
                    //Type dbHelperType = assembly.GetType("DB.SqlServer.SqlServerHelper");//2 获取类型 
                    object oDBHelper = Activator.CreateInstance(dbHelperType);//3 创建对象
                    IDBHelper dbHelper = (IDBHelper)oDBHelper;//4 接口强制转换
                    dbHelper.Query();//5 方法调用
                }
                watch.Stop();
                reflectionTime = watch.ElapsedMilliseconds;
            }

            Console.WriteLine($"commonTime={commonTime} reflectionTime={reflectionTime}");
        }
    }
}

9、反射调用字段属性

{
//反射调用字段属性
Type type = typeof(People);
object oInstance = Activator.CreateInstance(type);
//反射赋值
foreach (PropertyInfo prop in type.GetProperties())
{
if (prop.Name == "Id")
{
prop.SetValue(oInstance, 1234);
}
else if (prop.Name == "Name")
{
prop.SetValue(oInstance, "RoseLoves");
}
}

//反射取值
foreach (PropertyInfo prop in type.GetProperties())
{
Console.WriteLine($"{prop.Name} = {prop.GetValue(oInstance)}");
}
}

10、反射+ADO.NET 实现ORM框架

1、实现基本的查询功能

using DB.Interface;
using Microsoft.Data.SqlClient;
using System.Reflection;

namespace DB.SqlServer
{
    public class SqlServerHelper : IDBHelper
    {
        private readonly string _ConnectionStr;
        public SqlServerHelper(){ }
        public SqlServerHelper(string connectionStr)
        {
            _ConnectionStr = connectionStr;
        }
        public void Query() { }

        public List<T> GetCompany<T>(int id)
        {
            //1.准备数据库连接字符串
            //_ConnectionStr
            //2.创建连接对象
            SqlConnection connection = new SqlConnection(_ConnectionStr);
            connection.Open();//打开连接
            //反射创建属性
            List<T> list = new List<T>();
            Type type = typeof(T);
            object oInstance = Activator.CreateInstance(type);
            //3.准备命令,Sql语句
            //string sql = $"SELECT * FROM Company WHERE ID = '{id}'";
            string sql = $"SELECT {string.Join(',', type.GetProperties().Select(c => c.Name).ToList())} FROM {type.Name} WHERE ID = {id}";
            //4.准备命令执行对象
            SqlCommand command = new SqlCommand(sql, connection);
            //执行命令(执行sql语句)
            SqlDataReader reader = command.ExecuteReader();
            while (reader.Read())
            {
                //反射取值
                foreach (PropertyInfo prop in type.GetProperties())
                {
                    prop.SetValue(oInstance, reader[prop.Name] is DBNull ? null : reader[prop.Name]);
                }
                list.Add((T)oInstance);
            }
            return list;
        }
    }
}

{
//反射+AOD.NET 实现ORM框架
string constr = "Data Source=LAPTOP-FR93A6FM;Initial Catalog=CustomerDB;Persist Security Info=True;User ID=sa;Password=Xjc000000;Trust Server Certificate=True";
SqlServerHelper sqlServerHelper = new SqlServerHelper(constr);
var c = sqlServerHelper.GetCompany<Company>(13479);
Console.WriteLine(c[0].Name);
var S = sqlServerHelper.GetCompany<SysUser>(13479);
}

2、但是在上述操作中,SQL语句在每次执行都要创建一次,用反射创建对象会有性能损耗。所以可以用缓存

Sql语句的生成特点:

​ a、同类型的sql语句是一样的

​ b、同一类型的操作,sql语句只需要生成一次

​ c、如果要缓存,为每一个类型做一个缓存,也就是泛型缓存:泛型缓存的本质是泛型类。

namespace DB.SqlServer
{
    public class SqlBuilder<T>
    {
        private static string _QuerySql;
        /// <summary>
        /// 使用静态构造函数初始化
        /// </summary>
        static SqlBuilder()
        {
            Type type = typeof(T);
            _QuerySql = $"SELECT {string.Join(',', type.GetProperties().Select(c => c.Name).ToList())} FROM {type.Name} WHERE ID =";
        }

        public static string GetQuerySql(int id) => $"{_QuerySql} {id}";
    }
}

using DB.Interface;
using DB.Models;
using Microsoft.Data.SqlClient;
using System.Reflection;

namespace DB.SqlServer
{
    public class SqlServerHelper : IDBHelper
    {
        private readonly string _ConnectionStr;
        public SqlServerHelper() { }
        public SqlServerHelper(string connectionStr)
        {
            _ConnectionStr = connectionStr;
        }
        public void Query() { }

        public List<T> GetCompany<T>(int id) where T : BaseModel//要求实体类必须有一个Id的字段
        {
            //1.准备数据库连接字符串
            //_ConnectionStr
            //2.创建连接对象
            SqlConnection connection = new SqlConnection(_ConnectionStr);
            connection.Open();//打开连接
            //反射创建属性
            List<T> list = new List<T>();
            Type type = typeof(T);
            object oInstance = Activator.CreateInstance(type);
            //3.准备命令,Sql语句
            //string sql = $"SELECT * FROM Company WHERE ID = '{id}'";
            //string sql = $"SELECT {string.Join(',', type.GetProperties().Select(c => c.Name).ToList())} FROM {type.Name} WHERE ID = {id}";
            string sql = SqlBuilder<T>.GetQuerySql(id);
            //4.准备命令执行对象
            SqlCommand command = new SqlCommand(sql, connection);
            //执行命令(执行sql语句)
            SqlDataReader reader = command.ExecuteReader();
            while (reader.Read())
            {
                //反射取值
                foreach (PropertyInfo prop in type.GetProperties())
                {
                    prop.SetValue(oInstance, reader[prop.Name] is DBNull ? null : reader[prop.Name]);
                }
                list.Add((T)oInstance);
            }
            return list;
        }
    }
}

11、反射生成程序集

​ 原始:程序是设计好的,然后通过运行时环境去驱动,去执行设计好的程序指令;

​ EMit:在程序运行的过程中,动态的生成一堆新的程序出来-------程序造程序。

在程序运行时,要能够动态的生成程序集、类、结构、变量、方法、属性、字段。。。。。。

程序集(dll/exe)--->moudle----->类------>方法、属性。。。。。他们是逐级的包含关系

using System.Reflection;
using System.Reflection.Emit;

namespace MyReflecttion
{
    public class ReflectionEmit
    {
        //一般的,使用反射发出(reflection emit)可能会是这样子的步骤:
        //步骤一、创建一个新的程序集(程序集是动态的存在于内存中或把它们保存到磁盘上)。 
        //步骤二、在程序集内部,创建一个模块(module)。
        //步骤三、在模块内部,创建一个类型。
        //步骤四、给类型添加属性和方法。
        //步骤五、产生属性和方法内部的代码

        //确切得说,当你使用Reflection.Emit类产生代码时,以上描述的是你实际中要遵循的过程。

        public static void Show()
        {
            AssemblyName aName = new AssemblyName("DynamicAssemblyExample");

            //程序集建造者
            AssemblyBuilder ab = AssemblyBuilder.DefineDynamicAssembly(aName,
                AssemblyBuilderAccess.RunAndCollect);

            // 对于单个模块程序集,模块名称通常为 
            //程序集名称加上扩展名。 
            ModuleBuilder mb = ab.DefineDynamicModule("MyModal");

            //基于module 配置要生成的类型
            TypeBuilder tb = mb.DefineType("MyDynamicType", TypeAttributes.Public);

            // 添加int(Int32)类型的私有字段。
            FieldBuilder fbNumber = tb.DefineField("m_number",
                typeof(int), FieldAttributes.Private);

            // 定义一个接受一个int类型参数的构造函数 
            // 储存在私人区域。 
            Type[] parameterTypes = { typeof(int) };
            ConstructorBuilder ctor1 = tb.DefineConstructor(
                MethodAttributes.Public,
                CallingConventions.Standard,
                parameterTypes);

            ILGenerator ctor1IL = ctor1.GetILGenerator();

            //对于构造函数,参数0是对新 
            //实例。在调用base之前将其推到堆栈上 
            //类构造函数。指定的默认构造函数 
            //通过传递 
            //类型(Type.EmptyTypes)到GetConstructor。 

            ctor1IL.Emit(OpCodes.Ldarg_0);
            ctor1IL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));

            //在推送参数之前,先将实例推送到堆栈上 
            //将被分配给私有字段m\u编号。

            ctor1IL.Emit(OpCodes.Ldarg_0);
            ctor1IL.Emit(OpCodes.Ldarg_1);
            ctor1IL.Emit(OpCodes.Stfld, fbNumber);
            ctor1IL.Emit(OpCodes.Ret);


            //定义无参数构造函数
            //定义提供默认值的默认构造函数 
            //私人领域。对于参数类型,传递空 
            //类型数组或传递null。 
            ConstructorBuilder ctor0 = tb.DefineConstructor(
                MethodAttributes.Public,
                CallingConventions.Standard,
                Type.EmptyTypes);

            ILGenerator ctor0IL = ctor0.GetILGenerator();

            //对于构造函数,参数0是对新 
            //实例。在推送默认值之前将其推送到堆栈上 
            //值,然后调用构造函数ctor1。 

            ctor0IL.Emit(OpCodes.Ldarg_0);
            ctor0IL.Emit(OpCodes.Ldc_I4_S, 42);
            ctor0IL.Emit(OpCodes.Call, ctor1);
            ctor0IL.Emit(OpCodes.Ret);

            //定义一个名为Number的属性,用于获取和设置私有 现场。 
            //DefineProperty的最后一个参数为null,因为属性没有参数(如果不指定null,则必须 
            //指定类型对象的数组。对于无参数属性, 
            //使用不带元素的内置数组:Type.EmptyTypes)

            PropertyBuilder pbNumber = tb.DefineProperty(
                "Number",
                PropertyAttributes.HasDefault,
                typeof(int),
                null);


            //属性“set”和属性“get”方法需要特殊的属性集。 
            MethodAttributes getSetAttr = MethodAttributes.Public |
                MethodAttributes.SpecialName | MethodAttributes.HideBySig;

            //为Number定义“get”访问器方法。方法返回 
            //一个整数,没有参数(注意null可以是
            //代替类型使用。空类型) 
            MethodBuilder mbNumberGetAccessor = tb.DefineMethod("get_Number",
                getSetAttr, typeof(int), Type.EmptyTypes);

            ILGenerator numberGetIL = mbNumberGetAccessor.GetILGenerator();

            //对于实例属性,参数0是实例。加载 
            //实例,然后加载private字段并返回 
            //堆栈上的字段值。

            numberGetIL.Emit(OpCodes.Ldarg_0);
            numberGetIL.Emit(OpCodes.Ldfld, fbNumber);
            numberGetIL.Emit(OpCodes.Ret);

            // 为Number定义“set”访问器方法,该方法没有返回值 
            //类型并接受一个int(Int32)类型的参数。

            MethodBuilder mbNumberSetAccessor = tb.DefineMethod(
                "set_Number",
                getSetAttr,
                null,
                new Type[] { typeof(int) });

            ILGenerator numberSetIL = mbNumberSetAccessor.GetILGenerator();

            // 加载实例和数值参数,然后存储 



            numberSetIL.Emit(OpCodes.Ldarg_0);
            numberSetIL.Emit(OpCodes.Ldarg_1);
            numberSetIL.Emit(OpCodes.Stfld, fbNumber);
            numberSetIL.Emit(OpCodes.Ret);

            //最后,将“get”和“set”访问器方法映射到 
            //属性生成器。该属性现在已完成。

            pbNumber.SetGetMethod(mbNumberGetAccessor);
            pbNumber.SetSetMethod(mbNumberSetAccessor);

            // 定义一个接受整数参数并返回 
            //该整数与专用字段mèu数的乘积。这个 
            //同时,参数类型的数组是动态创建的。

            MethodBuilder meth = tb.DefineMethod(
                "MyMethod",
                MethodAttributes.Public,
                typeof(int),
                new Type[] { typeof(int) });

            ILGenerator methIL = meth.GetILGenerator();

            // 要检索private instance字段,请将实例加载到它 
            // 属于(参数0)。加载字段后,加载 
            // 参数一,然后乘。从方法返回 
            // 上的返回值(两个数字的乘积) 执行堆栈。

            methIL.Emit(OpCodes.Ldarg_0);
            methIL.Emit(OpCodes.Ldfld, fbNumber);
            methIL.Emit(OpCodes.Ldarg_1);
            methIL.Emit(OpCodes.Mul);
            methIL.Emit(OpCodes.Ret);

            // 完成类型
            Type t = tb.CreateType();

            // 下一行保存单个模块部件。这个 
            //需要AssemblyBuilderAccess包含Save。你现在可以了 
            //在命令提示符下键入“ildasm MyDynamicAsm.dll”,然后 
            // 检查组件。你也可以写一个程序 
            //对程序集的引用,并使用MyDynamicType类型。 



            //ab.bu(aName.Name + ".dll");

            //由于AssemblyBuilderAccess包含Run,因此可以 
            //立即执行。从获取反射对象开始 
            //方法和属性。  

            MethodInfo mi = t.GetMethod("MyMethod");
            PropertyInfo pi = t.GetProperty("Number");

            // 使用默认值创建MyDynamicType的实例  建造师。
            object o1 = Activator.CreateInstance(t);

            // 显示属性的值,然后将其更改为127并 
            //再次显示。使用null表示属性 
            //没有索引。

            Console.WriteLine("o1.Number: {0}", pi.GetValue(o1, null));
            pi.SetValue(o1, 127, null);
            Console.WriteLine("o1.Number: {0}", pi.GetValue(o1, null));

            //  调用MyMethod,传递22,并显示返回值22 
            // 乘以127。参数必须作为数组传递,即使 
            // 只有一个。



            object[] arguments = { 22 };
            Console.WriteLine("o1.MyMethod(22): {0}",
                mi.Invoke(o1, arguments));
            //  使用构造函数创建MyDynamicType的实例 
            //它指定了m\ U编号。构造函数由 
            //匹配参数数组中的类型。在这种情况下, 
            // 参数数组是动态创建的。显示 
            //属性值。


            object o2 = Activator.CreateInstance(t,
                new object[] { 5280 });
            Console.WriteLine("o2.Number: {0}", pi.GetValue(o2, null));

        }
    }
}

标签:进阶,C#,Type,GetType,语法,new,type,public,string
From: https://www.cnblogs.com/SevenDouble/p/18647473

相关文章

  • 理解 QOverload<T>::of(&ClassName::MethodName);
    这段代码的语法是Qt信号与槽机制的现代实现方式之一,结合了C++11的lambda和模板特性。这里的QOverload是一个Qt提供的工具,用于解决Qt的信号和槽机制在多重重载函数时可能发生的歧义问题。以下是分解此代码的详解:1.connect的语法connect(sender,signal,re......
  • 【prometheus】【blackbox_exporter】grafna导入blackbox_exporter看板配置
    1、进入到grafana看板,选择合适的看板模版地址:https://grafana.com/grafana/dashboards/在搜索框中输入blackbox_exporter,找到合适的模版,如下图所示:2、点击并下载对应看板JSON数据3、在grafana的页面进行导入操作3.1点击importer按钮在左侧的Dashboards按钮,然后点......
  • 大二Web课程设计——张家界旅游网站设计与实现(HTML+CSS+JavaScript) (2)
    ......
  • 详解AQS五:深入理解共享锁CountDownLatch
    CountDownLatch是一个常用的共享锁,其功能相当于一个多线程环境下的倒数门闩。CountDownLatch可以指定一个计数值,在并发环境下由线程进行减一操作,当计数值变为0之后,被await方法阻塞的线程将会唤醒。通过CountDownLatch可以实现线程间的计数同步。为什么说CountDownLatch是一种共享......
  • celery+flask+数据库一个队列执行多个任务出现死锁
    celery创建一个共享队列rpa,该队列下有一个轮循任务和执行任务轮循任务会读取redis队列,循环队列并根据任务情况执行任务轮循间隔为1s,每次轮循都会循环队列的所有任务启动命令为celery-Aapp.celeryworker-Pgevent-c1--loglevelINFO-Qrpa此时设置并发数为1时,用......
  • 学习笔记:C#高级进阶语法——泛型
    一、Generic(泛型)1、泛型的定义:通用的类型就是泛型//在一个方法,传入的参数不确定的时候,我们可能要重写多次这个方法publicvoidShow(stringt){Console.WriteLine($"Thisis{typeof(CommonMethod).Name},parameter={t.GetType().Name},type={t}");}publicvoidShow(i......
  • opencv的亚像素角点检测函数cornerSubPix
    在OpenCV中,cornerSubPix函数用于对角点的亚像素精确化。这个函数可以提高角点检测的精度,通常在角点检测之后使用,如在Harris或Shi-Tomasi角点检测之后。函数原型voidcv::cornerSubPix(InputArrayimage,InputOutputArraycorners,SizewinSize,Size......
  • Conda基本使用
    Conda是跨平台的可用于在Windows、macOS和Linux上管理python环境和包的工具;方便在不同项目中创建隔离的python环境,解决python版本或包依赖带来的问题。环境管理Conda版本conda--version更新Conda到最新版本condaupdateconda查看主机存在的cuda环境condaenv......
  • 统信UOS报错qt.qpa.plugin:Could not load the Qt platform plugin "xcb" in “***”
    问题截图: 解决方案:执行命令sudoln-fs/usr/lib/x86_64-linux-gnu/libxcb-util.so.0/usr/lib/x86_64-linux-gnu/libxcb-util.so.1 参考链接:Ubuntu22.04中解决CouldnotloadtheQtplatformplugin“xcb“问题解决方法_couldnotloadtheqtplatformplugin"xcb......
  • CSharp (C#) 中创建Task 的7种方法对比,你用对了吗?
    在C#编程中,Task是用于异步编程的重要工具之一。了解不同创建Task的方式以及它们之间的区别,对提高编程效率和代码质量至关重要。本文将详细探讨几种常见的Task创建方式,并分析它们的使用场景及优缺点。一、使用Task.Run方法1.概述Task.Run是最常见的一种创建Task的方式。它接......