C# 反射

本文介绍了C#中的反射机制,包括反射的基本信息和使用方法。反射允许在运行时获取程序集、模块和类型的信息,动态创建实例、调用方法。文中详细解释了程序集的概念和特性,并探讨了如何利用反射加载、操作类型,以及在不同场景下使用typeof()和.GetType()的区别。还提供了创建对象、调用方法、操作字段和属性以及处理泛型的实例。
摘要由CSDN通过智能技术生成

一、反射的基本信息

反射使你能够获取有关加载的程序集和其中定义的类型的信息,同时可以在运行时创建、调用和访问类型实例。

反射提供封装程序集、模块和类型的对象。可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。

那么什么是程序集呢?

程序集包含模块、模块包含类型,而类型包含成员。在 .NET Core 和 .NET Framework 中,可以从一个或多个源代码文件生成程序集,而程序集又可以包含一个或多个模块。

程序集具有以下属性:

  • 程序集以 .exe 或 .dll 文件的形式实现。

  • 对于面向 .NET Framework 的库,可以通过将程序集放入全局程序集缓存 (GAC),在应用程序之间共享程序集。必须先对程序集进行强命名,然后才能将它们包含到 GAC 中。有关详细信息,请参阅具有强名称的程序集。

  • 只有在需要使用时才会将程序集加载到内存中。如果未使用程序集,则不加载。也就是说,使用程序集,可以在大型项目中高效管理资源。

  • 可以使用反射,以编程方式获取程序集的相关信息。

  • 你可以加载一个程序集,以使用 .NET Core 中的 MetadataLoadContext 类以及 .NET Core 和 .NET Framework 中的 Assembly.ReflectionOnlyLoad 或 Assembly.ReflectionOnlyLoadFrom 方法来检查该程序集。

公共语言运行时中的程序集

程序集向公共语言运行时(CLR)提供了注意类型实现代码所需的信息。对于运行时,类型不存在于程序集上下文之外。

程序集定义以下信息:

  • 公共语言运行时执行的代码,每个程序集只能有一个入口点:DllMain、WinMain 或 Main。

  • 安全边界。程序集就是在其中请求和授予权限的单元。

  • 类型边界。每一类型的标识均包括该类型所驻留的程序集的名称。在一个程序集的范围中加载的称为 MyType 的类型不同于在另一个程序集范围中加载的称为 MyType 的类型。

  • 引用范围边界。程序集清单包含用于解析类型和满足资源请求的元数据。该清单指定要在程序集外公开的类型和资源,并枚举它所依赖的其他程序集。除非可迁移可执行 (PE) 文件中的 Microsoft 中间语言 (MSIL) 代码具有相关的程序集清单,否则不执行此代码。

  • 版本边界。程序集是公共语言运行时中无版本冲突的最小单元。同一程序集中的所有类型和资源均会被版本化为一个单元。程序集清单描述你为任何依赖项程序集所指定的版本依赖性。

  • 部署单元。当一个应用程序启动时,只有该应用程序最初调用的程序集必须存在。其他程序集(例如,包含本地化资源或实用工具类的程序集)可以按需检索。 这样,应用在第一次下载时就会比较精简。

  • 并行执行单元。

Module(模块)

模块是可移植的可执行文件,以.dll 或 .exe文件实现,由一个或多个类和接口组成。 单个模块可包含多个命名空间,而一个命名空间可跨越多个模块。

二、反射的使用

使用反射,如果事先知道对象名称,可以用 typeof,如果知道某个实例,可以用 .GetType() 获取某个实例的 Type,如果都不知道,或者想知道某个程序集内所有的类,可以先加载程序集,然后获取某个具体的 Type 对象,也可以获取该程序集内部所有的 Type 对象,如果要设置/获取字段、属性的值或者调用实例方法,需要创建该对象的实例,如果仅仅查看属性、字段的名称/类型,方法的名称/参数类型/参数名称/返回值,则不需要创建某一 Type 对象的实例。

typeof() 和 .GetType() 的区别: typeof()一般用于某一类/类型,获取其 Type,不需要其实例化对象,.GetType()是获取某一实例的 Type。

测试:

先创建一类库,名称为SimpleDLL,然后新建3个类,分别为MyClass1、GenericClass、CommonClass
在这里插入图片描述
MyClass1类:

public class MyClass1
{
   
    public string name;
    public int age;
    private string address;

    private string MyName {
    get; set; }
    public int MyAge {
    get; set; }
    private string MyAddress {
    get; set; }

    public MyClass1()
    {
   
        Console.WriteLine("这是公共的无参构造函数");
    }

    public MyClass1(int m)
    {
   
        Console.WriteLine("这是公共的有参构造函数,参数具有 {0} 类型", m.GetType());
    }

    private MyClass1(int m, int n)
    {
   
        Console.WriteLine("这是私有的有参构造函数,参数具有 {0} 和 {1} 类型", m.GetType(), n.GetType());
    }

    public void Test1()
    {
   
        Console.WriteLine("这是 Test1 方法");
    }

    public void Test2(int m)
    {
   
        Console.WriteLine("这是 Test2 方法,参数具有 {0} 类型", m.GetType());
    }

    public void Test3(int m, int n)
    {
   
        Console.WriteLine("这是 Test3 方法,参数具有 {0} 和 {1} 类型", m.GetType(), n.GetType());
    }

    public void Test3(string m, string n)
    {
   
        Console.WriteLine("这是 Test3 方法,参数具有 {0} 和 {1} 类型", m.GetType(), n.GetType());
    }

    private void Tset4()
    {
   
        Console.WriteLine("这是私有方法");
    }

    private void Test5(int m)
    {
   
        Console.WriteLine("这是私有方法,参数具有 {0} 类型", m.GetType());
    }
}

GenericClass类:

/// <summary>
/// 泛型类
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="W"></typeparam>
public class GenericClass<T
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值