C#反射知识点

程序集

程序集是经由编译器编译得到,供进一步编译执行的那个中间产物,在Windows系统中一般是后缀为.dll的库文件或者.exe的可执行文件

即我们所写的代码被编译器编译后得到的供人使用的代码集合

元数据

有关程序及其类型的数据被称为元数据,比如程序中的类、类中的函数、变量等等信息就是程序的元数据,保存在程序集中

反射的概念

程序在运行时可以查看其他程序集或者自身的元数据,这个查看的行为叫做反射

即在程序运行时,通过反射可以得到其他程序集或者自身程序集代码的各种信息,如类、函数、变量、对象等等,能够实例化、执行、操作它们

反射的作用

由于反射可以在程序编译后获得信息,他提高了程序的拓展性和灵活性。

在程序运行时获取所有的元数据,包括元数据的特性

程序运行时实例化对象操作对象

程序运行时创建新的对象用这些对象执行任务

语法相关

Type

类的信息类,是反射的基础,是访问数据的主要方式,使用Type的成员获取有关类型声明的信息,有关类型的成员(如:构造函数、方法、字段、属性和类的事件)

获取Type

//通过Object中的GetType()来的到对象的type
int a = 1;
Type type = a.GetType();
Console.WriteLine(type);
            
//通过typeof()关键字传入类名也能得到对象的type
Type type1 = typeof(int);
            

//用过类名也能获取type
//注意类名必须包含命名空间,不然找不到
//Type type2 = Type.GetType("Int32");  这样不行
Type type2 = Type.GetType("System.Int32");
Console.WriteLine(type2);
Console.WriteLine(type1);

得到类的程序集信息

System.Console.WriteLine(type.Assembly);

获取类中的公共成员

class Test
{
    private int i = 1;
    public int j = 0;
    public string s = "123";
    public Test() { }
    public Test(int i)
    {
        this.i = i;
    }
    public Test(int i, string s) : this(i)
    {
        this.s = s;
    }
    public void Speak()
    {
        Console.WriteLine(i);
    }
}

得到type

Type t = typeof(Test)

得到所有的公共成员(需要引用命名空间using System.Reflection)

MemberInfo[] infos = t.GetMembers();
for(int i = 0; i < infos.Length; i++)
{
    Console.WriteLine(infos[i]);
}

得到所有构造函数

ConstructorInfo[] constructors = t.GetConstructors();
for(int i=0; i < constructors.Length; i++)
{
    Console.WriteLine(constructors[i]);
}

获取其中一个构造函数并执行

得到构造函数要传入Type数组,数组中的内容按顺序是构造函数的参数类型

执行构造函数要传入Object数组,表示按顺序传入的参数

无参构造:

ConstructorInfo info = t.GetConstructor(new Type[0]);
Test obj = info.Invoke(null) as Test;//没有参数传入null
Console.WriteLine(obj.j);

有参构造:

ConstructorInfo info1 = t.GetConstructor(new Type[] { typeof(int) });
obj = info1.Invoke(new object[] { 3}) as Test;
Console.Write(obj.s);

ConstructorInfo info2 = t.GetConstructor(new Type[] {typeof(int),typeof(string) });
obj = info2.Invoke(new object[] { 4,"44444" }) as Test;
Console.WriteLine(obj.s);

获取类中的公共成员变量

获取所有公共成员变量:

FieldInfo[] fieldInfos = t.GetFields();
for(int i = 0;i < fieldInfos.Length;i++)
{
    Console.WriteLine(fieldInfos[i]);
}

得到指定名称的公共成员变量

FieldInfo infoj = t.GetField("j");
Console.WriteLine(infoj);

通过反射获取和设置对象的值

Test test = new Test();
test.j = 111;
test.s = "ssss";
Console.WriteLine(infoj.GetValue(test));

infoj.SetValue(test, 222);
Console.WriteLine(infoj.GetValue(test));

获取和调用类的公共成员方法

Type strType = typeof(string);
MethodInfo[] methods = strType.GetMethods();
for(int i = 0; i < methods.Length;i++)
{
    Console.WriteLine(methods[i]);
}
MethodInfo subStr = strType.GetMethod("Substring",
    new Type[] {typeof(int),typeof(int)});//如果存在重载通过Type数组中的内容进行区分

string str = "Hello,World!";
//调用方法,如果是静态方法Invoke中第一个参数传null,因为不需要对象来调用该方法
Object res =  subStr.Invoke(str, new object[] { 7, 5 });
Console.WriteLine(res);

Assembly

程序集类,主要用来加载其他程序集,加载后才能用Type来使用其他程序集中的信息

若要使用非自身程序集中的内容,要先加载程序集,如dll文件(库文件,可以看成一个代码仓库,她提供给我们一些可以直接拿来使用的变量、函数或类)

三种加载程序集的函数

一、一般用来加载同一文件夹下的其他程序集

Assembly assembly = Assembly.Load();//参数为 程序集名称

二、一般用来加载在不同文件夹下的其他程序集

Assembly assembly1 = Assembly.LoadFrom();//参数为 路径+dll文件名
Assembly assembly2 = Assembly.LoadFile();//参数为 要加载的文件的完全限定路径

 @可以取消转义字符

加载一个指定数据集

Assembly assembly1 = Assembly.LoadFrom();

 加载数据集中的类对象

//例举有什么类
Type[] types = assembly1.GetTypes();
for(int i = 0;i < types.Length;i++) 
{
    Console.WriteLine(types[i]);
}
Type icon = assembly1.GetType("***.Icon");//加载***环境下的Icon类
//例举该类下有什么成员
MemberInfo[] members = icon.GetMembers();
for(int i = 0; i < members.Length;i++)
{
    Console.WriteLine(members[i]);
}

实例化类对象 

由于Icon构造函数中有用到另外一个在该数据集中的枚举,故若要实例化一个Icon对象就得先实例化该枚举对象

Type moveDir = assembly1.GetType("***.MoveDir");
FieldInfo right = moveDir.GetField("Right");
//由于枚举没有对象,故可以通过right.getValue(null)来得到枚举
object iconObj = Activator.CreateInstance(icon,10,5,right);

通过反射得到对象中的方法

clear.Invoke(iconObj, null);

Activator

用于快速实例化对象的类,用于将Type对象快捷实例化为对象,先得到Type然后快速实例化一个对象

Type testType = typeof(Test);

无参构造

Test testObj = Activator.CreateInstance(testType) as Test;
Console.WriteLine(testObj);

有参构造

类型后面的参数就是构造函数中的参数,要一一对应不然会报错

testObj = Activator.CreateInstance(testType, 11) as Test;
Console.WriteLine(testObj);

testObj = Activator.CreateInstance(testType, 11,"123") as Test;
Console.WriteLine(testObj);

应用

新建一个类库工程,内有Player类,内含姓名构造函数等信息

Assembly assembly3 = Assembly.LoadFrom(@"***");//路径+dll文件名,后缀可加可不加
Type[] t1 = assembly3.GetTypes();
for(int i = 0; i < t1.Length; i++)
{
    Console.WriteLine(t1[i]);
}
Type player = assembly3.GetType("***.Player");
Object objplayer = Activator.CreateInstance(player);
Console.WriteLine(objplayer);

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值