C#学习笔记 反射

28 篇文章 0 订阅

Type对象

要使用反射,首先要获取Type对象。Type对象包含C#对象的各种信息,例如名称,命名空间的名称等等。使用typeof 运算符,可以从一个类名获取Type对象。

Type type = typeof(int);

还可以在Object对象上调用GetType方法来获取一个Type对象。

Type type = i.GetType();

获得Type对象之后,就可以调用上面的方法和属性,来查看有关类型的信息了。注意Type对象查看的类的信息,而不是具体绑定到某个对象的信息。

Console.WriteLine($"基类是:{type.BaseType}");
Console.WriteLine($"类型全名是:{type.FullName}");
Console.WriteLine($"所在的程序集是:{type.Assembly}");
Console.WriteLine($"该类型是否是接口:{type.IsInterface}");

ParameterInfo对象

通过ParameterInfo对象可以得到参数的信息。详细情况可以查看MSDN库。

MemberInfo对象

通过MemberInfo对象可以查看有关类中成员的信息。其中有大量的方法和属性,详情可以参阅MSDN。

MemberInfo的ToString()方法返回成员信息的字符串。所以我们可以这样简单的获取一个类的所有成员信息。

MemberInfo[] members = type.GetMembers();
foreach (MemberInfo member in members)
{
    Console.WriteLine($"{member}");
}

MethodInfo对象

利用MethodInfo对象,我们可以知道关于方法的大量信息,详情请参阅MSDN库。

在这里,我们利用MethodInfo和ParameterInfo对象,可以组合得到方法签名的信息。其实也可以简单的在遍历的时候使用MethodInfo对象的ToString()方法,但是这个方法只会返回方法参数列表的类型名,不会返回参数名。

MethodInfo[] methods = type.GetMethods();
foreach (MethodInfo method in methods)
{
    //创建新的字符串构造类,组合方法的信息
    StringBuilder sb = new StringBuilder();
    //组合方法返回值的类型
    sb.AppendFormat($"{method.ReturnParameter.ParameterType} ");
    //组合方法名称
    sb.AppendFormat($"{method.Name}(");
    //获得参数列表信息
    ParameterInfo[] parameters = method.GetParameters();
    foreach (ParameterInfo parameter in parameters)
    {
        //组合参数列表信息
        sb.AppendFormat($"{parameter}, ");
    }
    //删除参数最后的多余的逗号
    if (parameters.Length >= 1)
    {
        sb.Remove(sb.Length - 2, 2);
    }
    sb.Append(")");
    //组合完毕,显示字符串
    Console.WriteLine(sb.ToString());

读取并使用对象

上面的方法都是静态的读取某一个类的信息。其实利用反射还可以做更多事情,例如动态读取一个对象并执行其中的方法。

首先先来随意构造一个类。

class Otaku
{
    private string name;
    public Otaku()
    {
        name = "DefaultName";
    }
    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
        }
    }
    public string[] LovedCartoons()
    {
        return new string[] { "One Piece", "RWBY", "Sword Art Online" };
    }
}

然后就可以利用上面的步骤来动态获取并调用该对象的方法了。

MyConsole.PrintNextSection("动态获取对象");
Type type = typeof(Otaku);
Otaku otaku =(Otaku)type.GetConstructor(Type.EmptyTypes).Invoke(null);
PropertyInfo property = type.GetProperty("Name");
//原来的属性值
Console.WriteLine($"原值:{otaku.Name}");
property.SetValue(otaku, "new otaku");
//新的属性值
Console.WriteLine($"新值:{otaku.Name}");
//获取MethodInfo并动态调用
MethodInfo method = type.GetMethod("LovedCartoons");
string[] returnValues = (string[])method.Invoke(otaku, null);
foreach (string value in returnValues)
{
    Console.Write(value + ", ");
}
Console.WriteLine();

反射的作用

通过反射我们可以动态获取对象并调用方法。初看之下貌似没有什么作用,因为利用反射可以做到的事情不用反射照样也可以做到。其实,反射的最重要的作用就在于这动态 二字。

如果不利用反射,想要编写代码组合类的话,就必须硬编码到代码里面,这在某些情况下就不适用了。比如在编写Web程序的过程中,有很多工作都是相同的,如果每次都硬编码的话,不仅效率不高,而且很多情况下也容易犯错。这时候利用反射特性,将不变的工作固定下来,变动的工作分离出来,可以大大提高工作效率。不过真正的作用还是需要自己在实际工作中去体会。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值