深入浅出C#反射(Reflection)原理和应用场景

今天带领大家详详细细的把反射好好说一遍,反射包含的东西还是非常多的,首先在这里准备了一些简单的代码,有个Model类库,数据访问层的DB.SqlServer类库,数据访问层接口DB.Interface类库,以及MyReflection的控制台程序,其中DB.SqlServer继承DB.Interface:

我们想在Program的Main方法中调用DB.SqlServer类库中SqlServerHelper类中的查询方法Query。以往实现这种功能都是在MyReflection的控制台程序中引用DB.SqlServer和DB.Interface类库,才能调用Query方法,如下图所示:

以上这种方式调用其他类库的方法,相信对大家来说没什么难度,应该都会的。

关于dll---->IL---->Metadata---->反射


在讲反射之前,我们先来看下我们写的代码究竟是如何被计算机执行的,这里给大家画了个图,如下所示:

对于计算机来讲,它只认识01010101之类的二进制代码,人类写的高级语言(如C#、JAVA等)计算机是没法识别的,所以需要将高级语言转化为01让计算机可以识别的二进制编码,中间是有一个过程的。就拿C#来讲,VS编译器会将编写好的代码进行编译,编译后会生成exe/dll文件,.Net Core里面已经不生成exe了,都是dll。dll和exe还需要CLR/JIT的即时编译成字节码,才能最终被计算机执行。有伙伴就会问为什么要编译2次呢,先编译到dll,再编译到字节码01呢,为什么不能一次性编译成字节码呢?因为我们写的是C#语言,但是真实运行的机器有很多种,可能是32位,也可能是64位,操作系统可能是windows、linux、unix等,不同的计算机不同的操作系统识别字节码的可能是不一样的,但是从高级语言编译成exe/dll这一步是一样的。所以只要在不同运行环境的计算机上安装对应的不同的CLR/JIT,就可以运行我们同一个exe/dll了。这里就大概讲下这样一个过程,后面会有章节详细讲解程序如何被计算机执行的。现在我们先关注编译生成的exe/dll,它包含2部分,分别是中间语言IL和源数据元数据metadata。IL里面包含我们写的大量的代码,比如说方法、实体类等。元数据metadata不是我们写的代码,它是编译器在编译的时候生成的描述,它可能是把命名空间、类名、属性名记录了一下,包括特性。

反射加载dll,读取module、类、方法、特性

讲上面程序的编译过程跟反射有什么关系呢?我们反射就是读取metadata里面的数据的,然后去使用它。接下来通过反射的方式去实现调用DSqlServerHelper类中的查询方法Query:

反射创建对象(反射+简单工厂+配置文件)

可以从图中结果看出利用反射成功调用了DSqlServerHelper类下的查询方法Query。对比下最开始添加引用直接new SqlServerHelper()对象然后调取Query方法写的代码更少些,而利用反射需要多写好几行代码,貌似反射更麻烦些,那什么还要用反射呢?如果把using DB.SqlServer注释掉,就会发现new SqlServerHelper()会报错,而不会影响反射写的代码。也就是说反射在不添加引用,不new一个对象的情况下,可以动态的调取对象中的方法,这就是反射的好处。另外觉得这里反射的代码太多了,那是因为没封装,接下来封装下再去调用代码就少很多了。

<appSettings>
    <add key="IDBHelper" value="DB.SqlServer.SqlServerHelper,DB.SqlServer"/>
</appSettings>
namespace MyReflection
{
    public class SimpleFactory
    {
        private static string TypeDll = ConfigurationManager.AppSettings["IDBHelper"];
        private static string DllName = TypeDll.Split(',')[1];
        private static string TypeName = TypeDll.Split(',')[0];
        public static IDBHelper CreateHelper()
        {
            Assembly assembly = Assembly.Load(DllName);
            Type typeDBHelper = assembly.GetType(TypeName);
            object oDBHelper = Activator.CreateInstance(typeDBHelper);
            IDBHelper iDBHelper = oDBHelper as IDBHelper;
            return iDBHelper;
        }
    }
}

反射只能做这点事吗,仅仅就这么简单吗?当然不是的,现在是使用的sqlserver类库,假如程序需要扩展了,现在要从sqlserver换成mysql,或者是oracle。如果之前是用的添加引用类库的方式,然后new SqlServerHelper()对象去调用Query(),现在就要重新添加DB.MySql引用,然后改命名空间,并把new SqlServerHelper()改成new MySqlHelper()了。

但是在反射的做法里面就不一样了,我们只需要简单的升级下,把配置文件之前sqlserver的配置注释,改成mysql的就可以了:

<appSettings>
    <!--<add key="IDBHelper" value="DB.SqlServer.SqlServerHelper,DB.SqlServer"/>-->
	<add key="IDBHelper" value="DB.MySql.MySqlHelper,DB.MySql"/>
</appSettings>

反射的黑科技(多构造函数调用、破坏单例、创建泛型)

1、多构造函数的调用

上面反射都是调用类的无参构造函数,

2、调用私有的构造函数(破坏单例)

先说说单例模式,单例模式就是为了在我们的进程中

3、创建泛型

反射调用实例方法、静态方法、重载方法

1、调用实例方法

2、调用静态方法

3、调用重载方法

 

 

 

 

 

 

 

 

 

  • 23
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#是一种多线程语言,它提供了许多用于实现多线程应用程序的工具和库。在C#中,可以使用Thread类来创建和管理线程,也可以使用Task类来执行异步操作。 下面是一些深入浅出的讲解C#多线程的基础知识: 1. 线程的概念 线程是计算机中的基本执行单元。一个进程可以包含多个线程,每个线程可以独立执行特定的任务。在多线程应用程序中,多个线程可以同时执行不同的任务,提高了应用程序的性能和响应能力。 2. 线程的创建和启动 在C#中,可以使用Thread类创建和启动新线程。可以通过以下代码创建并启动一个新线程: ```csharp Thread thread = new Thread(new ThreadStart(MyMethod)); thread.Start(); ``` 其中,MyMethod是要在新线程中执行的方法。可以使用ThreadStart委托来引用该方法。 3. 线程的同步 在多线程应用程序中,如果多个线程同时访问共享资源,可能会导致数据不一致或其他问题。为了避免这些问题,可以使用线程同步机制来协调多个线程的执行。 C#中提供了多种线程同步机制,例如锁(lock)、互斥体(Mutex)、信号量(Semaphore)和事件(Event)。可以使用这些机制来确保线程间的同步和协调。 4. 线程的取消 在某些情况下,需要取消正在执行的线程。C#中提供了Cancellation Token机制来实现线程的取消。可以使用以下代码创建Cancellation Token: ```csharp CancellationTokenSource cts = new CancellationTokenSource(); ``` 然后,可以在执行线程的任务时检查Cancellation Token,如果Cancellation Token已经被取消,则可以停止任务的执行: ```csharp if (cts.Token.IsCancellationRequested) { // 停止任务的执行 } ``` 5. 异步编程 在C#中,还可以使用异步编程模型来实现多线程应用程序。可以使用async和await关键字来定义异步方法,以及使用Task类来执行异步操作。 异步编程可以提高应用程序的性能和响应能力,同时使代码更易于阅读和维护。 以上是C#多线程的基础知识,如果想深入学习,可以查阅相关资料,例如MSDN文档或相关书籍。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值