2:什么是反射与反射的应用及调用方法(by-朝夕)

前言

程序编译流程

1.ILspy:逆向工程:可以把Dll/Exe文件反编译回来;
2.IL:是对标于C#代码的代码,不太好阅读
3.metadata:是一个清单数据,只是记录有什么,而不是展示所有的实现;明细账本
4.反射是System.Reflection命名空间,可以读取metadata,并使用metadata;是微软提供的一个帮助类库;
5.下图举例使用ILSpy打开我写的一个实体类。如果使用IL方式呢,我们看到的程序不是很明朗。
IL
6.如果使用C#查看,就可以得到我原本写的代码了。
c#

为什么学习反射

答:因为反射真的是无处不在,ORM/MVC/IOC;

  1. 在MVC编程中比如 “Home/Index” 这样的路径来访问程序文件中的特定类。其实用到的就是反射。
  2. 可以利用反射来生成实体类对象。
  3. 可以利用反射来根据实体类生成自动的查询语句与返回对象。
  4. 反射可以实现程序的解耦(不需要添加项目引用即可使用类)。
  5. 反射可以实现动态配置来实现程序的高可用。

1.反射创建对象

目录结构

1.目前的结构如上图。调用的方法如下图与代码。
获取对象图
2.加载dll动态库有很多种方式,推荐使用这种方式Assembly.LoadFrom原因:

  • 不需要添加对dll的引用,只需要把dll拷贝到发布目录下即可使用。
  • 不需要全路径,只需要写上DLl的名称即可。PS:后缀要加上 .dll
public static IDBHelper getClass()
        {
            //获取数据清单metadata
            Assembly assembly3 = Assembly.LoadFrom(@"HomeWork.SqlHelper.dll"); //dll名称(需要后缀) 
            ///2.获取类型
            Type type = assembly3.GetType("HomeWork.SqlHelper.SqlServerHelper");
            //创建实例
            object obj = Activator.CreateInstance(type);
            //类型转换。
            return obj as IDBHelper;
        }

2.反射调用方法

通过在上边的简单工厂后,我们实例出来一个接口对象IDBHelper。
接下来就可以通过接口点方法进行使用。

调用方法

			Console.WriteLine("获取反射类开始!");
            IDBHelper iDBHelper = SimpleFactory.getClass();
            5.调用方法
            Company company = iDBHelper.Find(1);
            Console.WriteLine("获取反射类完成!");

3.反射调用带参数构造方法

{ 
                Console.WriteLine("*********************Reflection创建带构造函数参数的对象*************************");
                Assembly assembly3 = Assembly.LoadFrom("HomeWork.SqlHelper.dll"); //dll名称(需要后缀)  
                Type type = assembly3.GetType("HomeWork.SqlHelper.SqlServerHelper");
                object obj = Activator.CreateInstance(type);
                object obj1 = Activator.CreateInstance(type, new object[] { "你好" });
                object obj2 = Activator.CreateInstance(type, new object[] { 123 });
                object obj3 = Activator.CreateInstance(type, new object[] { 123, "你好" });
                Type type1 = typeof(SqlServerHelper);
            }

调用参数方法

4.反射调用方法

{
    //Type type1 = typeof(ReflectionTest);
    //普通调用方式
    ReflectionTest reflectionTest = new ReflectionTest();
    reflectionTest.Show1();
    reflectionTest.Show2(123);
    reflectionTest.Show3(123);
    //reflectionTest.Show4
    ReflectionTest.Show5("Richard");

    //Console.WriteLine("*********************Reflection调用普通方法*************************");
    Assembly assembly3 = Assembly.LoadFrom("HomeWork.SqlHelper.dll"); //dll名称(需要后缀)  
    Type type = assembly3.GetType("HomeWork.SqlHelper.ReflectionTest");
    object objTet = Activator.CreateInstance(type);
    //objTet.Show();
    MethodInfo Show1 = type.GetMethod("Show1");
    object oResutl1 = Show1.Invoke(objTet, new object[] { });
    object oResutl = Show1.Invoke(objTet, new object[0]);

    MethodInfo Show2 = type.GetMethod("Show2");
    object oResutl2 = Show2.Invoke(objTet, new object[] { 123 });

    //Console.WriteLine("*********************Reflection调用普重载方法*************************");
    MethodInfo Show33 = type.GetMethod("Show3",new Type[] { typeof(DateTime)});
    object oResutl33 = Show33.Invoke(objTet, new object[] { DateTime.Now });
    Console.WriteLine($"{ typeof(DateTime) }>>>>>oResutl33执行完的参数值{oResutl33}");


    MethodInfo Show3 = type.GetMethod("Show3", new Type[] { typeof(int), typeof(string) });
    object oResutl3 = Show3.Invoke(objTet, new object[] { 123, "阳光下的微笑" });

    MethodInfo Show3_1 = type.GetMethod("Show3", new Type[] { typeof(string), typeof(int) });
    object oResutl3_1 = Show3_1.Invoke(objTet, new object[] { "明日梦", 234 });

    MethodInfo Show3_2 = type.GetMethod("Show3", new Type[] { typeof(int) });
    object oResutl3_2 = Show3_2.Invoke(objTet, new object[] { 345 });

    MethodInfo Show3_3 = type.GetMethod("Show3", new Type[] { typeof(string) });
    object oResutl3_3 = Show3_3.Invoke(objTet, new object[] { "赤" });

    MethodInfo Show3_4 = type.GetMethod("Show3", new Type[0]);
    object oResutl3_4 = Show3_4.Invoke(objTet, new object[] { });

    Console.WriteLine("*********************Reflection调用私有方法*************************");
    MethodInfo Show4 = type.GetMethod("Show4", BindingFlags.NonPublic | BindingFlags.Instance);
    object oResutl4 = Show4.Invoke(objTet, new object[] { "伟文" });

    MethodInfo Show5 = type.GetMethod("Show5", BindingFlags.Static | BindingFlags.Public);
    object oResutl5 = Show5.Invoke(objTet, new object[] { "追逐梦想的人。。" });
    object oResutl5_1 = Show5.Invoke(null, new object[] { "you。。" });

}

5.反射调用泛型类+泛型方法

Console.WriteLine("*********************Reflections实例化泛型类+调用泛型方法*************************");
{
    GenericMethod genericMethod = new GenericMethod();
    genericMethod.Show<int, string, DateTime>(123, "黄大仙", DateTime.Now);
    Assembly assembly3 = Assembly.LoadFrom("HomeWork.SqlHelper.dll"); //dll名称(需要后缀)  
    Type type = assembly3.GetType("HomeWork.SqlHelper.GenericMethod");
    object genericTest = Activator.CreateInstance(type);
    MethodInfo show = type.GetMethod("Show");
    //注意:需要指定泛型方法的泛型类型
    MethodInfo show1 = show.MakeGenericMethod(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
    show1.Invoke(genericTest, new object[] { 123, "黄大仙", DateTime.Now });//如果是泛型方法,需要先确定类型,再执行方法,注意:指定的类型和传入的参数类型必须匹配
}
//泛型类
{
    Assembly assembly3 = Assembly.LoadFrom("HomeWork.SqlHelper.dll"); //dll名称(需要后缀)  
    Console.WriteLine(typeof(GenericClass<,,>));
    //下面的方法未能成功获取到原因由于它是泛型类。要在声明类的时候就告知参数类型
    //Type type = assembly3.GetType("HomeWork.SqlHelper.GenericClass`3");                    
    //MethodInfo show = type.GetMethod("Show");
    //MethodInfo show2 = show.MakeGenericMethod(new Type[] { typeof(DateTime), typeof(int), typeof(string) });

    Type type = assembly3.GetType("HomeWork.SqlHelper.GenericClass`3");
    Type type1 = type.MakeGenericType(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
    object genericObj = Activator.CreateInstance(type1);
    MethodInfo show1 = type1.GetMethod("Show");
    show1.Invoke(genericObj, new object[] { 234, "工程师 冯", DateTime.Now });

    //GenericClass genericClass = new DB.SqlServer.GenericClass();
    GenericClass<int, string, DateTime> genericClass = new GenericClass<int, string, DateTime>();
    genericClass.Show(234, "工程师 冯", DateTime.Now);
}

6.反射的性能问题

  • 大家可以通过Stopwatch来监视下获取动态库再到被实例过程需要的时间。可以通过循环来测试。
  • 经测试确实发现反射会带来性能问题。但是仅在获取动态库与创建对象时耗时比较大。
  • 但是是在循环很多次的情况。这种可以通过代码优化来避免。比如。根本不会在循环里获取那么多次对象。把获取对象放在循环外就可以了。
  • 这样速度差异就可以忽略不计了。
    老师讲的一些好处
    //解耦:去掉对细节的依赖
    //如果你们的公司来了一个新的技术经理;说要搞MySql
    //反射来做,
    // 1.仅仅只需要实现MySqlHelper,
    // 2.Copy Dll文件
    // 3.修改配置文件
    //把数据库的版本给更换了
    //实现了程序的可配置;程序的课扩展;
    //反射破坏单例
    //反射可以突破方法的权限限制;

7.反射在框架中的应用

反射:IOC
反射应用于哪些框架;
IOC框架;反射+配置文件+工厂==IOC框架中应用;
反射--MVC
dll: HomeWork.SqlHelper.dll
type: HomeWork.SqlHelper.GenericDouble
就可以创建对象
type可以获取到Method===Method名称--字符串
  dll名称+类名称+方法名称===可以调用这个方法 
 localhost://Home/Index/123== 可以调用到MVC项目中的某一个Action,你们觉得这是用的什么技术?
MVC中调用方法就是反射的真实写照。。

反射在ORM中的应用: 
ORM---对象关系映射,就是通过对类的达成对数据库的操作;
方法、属性、字段

8.封装ORM数据库访问

//控制台程序
{
    SqlServerHelper sqlServerHelper = new SqlServerHelper();
    //Company company = sqlServerHelper.QueryCompany(1); 
    Company company = sqlServerHelper.Find<Company>(1);
    User user = sqlServerHelper.Find<User>(1);
    Console.WriteLine(company);
    Console.WriteLine(user);
}


//SqlServerHelper中的方法,通过反射结合泛型就能实现数据的查询。经过小扩展可以实现删除与添加数据。
public T Find<T>(int id) where T : BaseModel
        {
            string constr = "server=.;database=CustomerDB;uid=sa;pwd=sasa";

            Type type = typeof(T);
            object oResult = Activator.CreateInstance(type);

            var propList = type.GetProperties().Select(p => $"[{p.Name}]");
            string props = string.Join(",", propList);

            string sql = $"select {props} from  [{type.Name}] where id={id}";
            using (SqlConnection con = new SqlConnection(constr)) {
                using (SqlCommand command=new SqlCommand())
                {
                    command.Connection = con;
                    command.CommandText = sql;
                    con.Open();
                    SqlDataReader reader = command.ExecuteReader();
                    if (reader.Read())
                    {
                        foreach (PropertyInfo prop in type.GetProperties())
                        {
                            prop.SetValue(oResult, reader[prop.Name]);
                        }
                    }
                }
            }
            return oResult as T;
        }
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Lambda 表达式和反射可以很好地配合使用,可以通过反射动态调用方法,并将其与泛型方法结合,实现更加灵活的编程。 以下是一个示例,演示如何使用 Lambda 表达式、反射和泛型方法结合调用方法: ``` using System; using System.Linq.Expressions; using System.Reflection; class Program { static void Main(string[] args) { // 使用 Lambda 表达式创建一个 Func 委托 Func<int, int, int> addFunc = (x, y) => x + y; // 获取 addFunc 的 MethodInfo 对象 MethodInfo addMethodInfo = addFunc.Method; // 使用反射动态调用泛型方法 MethodInfo genericMethodInfo = typeof(Program).GetMethod("CallGenericMethod"); MethodInfo callMethodInfo = genericMethodInfo.MakeGenericMethod(addMethodInfo.ReturnType); // 构建参数 object[] parameters = new object[] { addMethodInfo, 1, 2 }; // 调用泛型方法 int result = (int)callMethodInfo.Invoke(null, parameters); Console.WriteLine("Result: " + result); } public static T CallGenericMethod<T>(MethodInfo method, object arg1, object arg2) { // 构建参数 object[] args = new object[] { arg1, arg2 }; // 调用方法 object result = method.Invoke(null, args); // 返回结果 return (T)result; } } ``` 在上面的示例中,我们首先创建了一个 Lambda 表达式,它是一个加法函数。然后,我们使用反射获取了该 Lambda 表达式对应的 MethodInfo 对象。接着,我们使用反射动态调用了泛型方法 CallGenericMethod,该方法接受一个 MethodInfo 对象和两个参数,并返回一个与 MethodInfo 对象返回类型相同的值。最后,我们通过反射调用了 CallGenericMethod 方法,并将参数传递给它。在 CallGenericMethod 方法内部,我们通过反射调用了传递的 MethodInfo 对象,实现了对 Lambda 表达式的调用,并返回了加法函数的结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值