• C#反射与特性(三):反射类型的成员


    上一篇文章中,介绍如何获取 Type 类型,Type 类型是反射的基础。

    本篇文章中,将使用 Type 去获取成员信息,通过打印出反射获取到的信息,为后续操作反射打好基础。


    1,获取类型的信息

    我们常常可以看到 函数、方法这两个词,很多人对此进行了混用。

    方法,就是 public void Test(){} 这样的形式;

    函数,指具有确定命名的、并且可以通过名称调用的代码,属性、字段、方法、委托、事件等;

    只要能够通过确定的名称调用(使用)的代码块,就是函数;而方法就是 返回值、名称、参数等组成的代码块;

    要操作反射,首先要获取到 类型 的反射信息,而类型的 Type ,与以下多种类型密切相关。

    类型 说明
    Assembly 加载程序集、读取程序集信息、获取类型等
    Module 访问程序集中的一个或多个模块
    PropertyInfo 类型的属性信息
    FieldInfo 类型的字段信息
    ConstructorInfo 类型的构造函数信息
    MethodInfo 类型的方法
    ParameterInfo 构造函数或方法的参数
    EventInfo 类型的事件
    MemberInfo 成员信息,集成以上除 Assembly、Module 外所有的类型

    1.1 类型的基类和接口

    1.1.1 基类

    C# 中,一个类型只能继承一个类型(基类型),使用实例Type.BaseType 属性,可以获取到此类型的基类型。

                Type type = typeof(MyClass);
                Type baseType = type.BaseType;
    

    1.1.2 获取实现的接口

    GetInterface()GetInterfaces() 可以获取类型实现的接口。

    示例

                Type type = typeof(System.IO.FileStream);
                Type[] list = type.GetInterfaces();
                foreach (var item in list)
                    Console.WriteLine(item.Name);
    

    输出

    IDisposable
    IAsyncDisposable
    

    1.1.3 获取泛型接口

                Type type = typeof(List<>);
                Type one = type.GetInterface("IList`1");
                Console.WriteLine(one.Name);
                Console.WriteLine("***************");
                Type[] list = type.GetInterfaces();
                foreach (var item in list)
                    Console.WriteLine(item.Name);
    

    输出

    IList`1
    ***************
    IList`1
    ICollection`1
    IEnumerable`1
    IEnumerable
    IList
    ICollection
    IReadOnlyList`1
    IReadOnlyCollection`1
    

    注意的是,如果要通过名称获取接口 Type ,需要使用 泛型类别的名称,例如 IList1`。

    1.2 获取属性、字段成员

    1.2.1 构造函数

    一个类型最少不了的就是构造函数,即使没有编写构造函数,C# 编译时也会生成默认的构造函数。

    GetConstructor()GetConstructors() 可以获取构造函数 ConstructorInfo 类型;

    ConstructorInfoGetParameter()GetParameters() 可以获取构造函数的参数信息;

    创建一个类

        public class MyClass
        {
            static MyClass() { }
            public MyClass() { }
            private MyClass(string a) { }
            public MyClass(int a) { }
        }
    

    打印

                Type type = typeof(MyClass);
                ConstructorInfo[] list = type.GetConstructors();
                foreach (var item in list)
                {
                    Console.WriteLine(item.Name + "   |   " + item.IsStatic + "   |   " + item.IsPublic);
                    ParameterInfo[] parms = item.GetParameters();
                    foreach (var itemNode in parms)
                    {
                        Console.WriteLine(itemNode.Name + "   |   " + itemNode.ParameterType + "    |   " + itemNode.DefaultValue);
                    }
                }
    

    输出

    .ctor   |   False   |   True
    .ctor   |   False   |   True
    a   |   System.Int32    |
    

    上面结果说明了,只能获取 Public 的构造函数;

    关于 ConstructorInfo 的使用方法,可以参考这里 https://docs.microsoft.com/zh-cn/dotnet/api/system.reflection.constructorinfo?view=netcore-3.1

    1.2.2 属性

    使用 GetPropertie()GetProperties() 可以获取 类型 的一个或多个属性。

                Type type = typeof(Type);
                PropertyInfo[] list = type.GetProperties();
                foreach (var item in list)
                    Console.WriteLine(item.Name + "	|	" + item.PropertyType);
    

    输出

    IsInterface  |  System.Boolean
    MemberType  |  System.Reflection.MemberTypes
    Namespace  |  System.String
    AssemblyQualifiedName  |  System.String
    FullName  |  System.String
    Assembly  |  System.Reflection.Assembly
    Module  |  System.Reflection.M
    

    1.2.3 字段

    使用 GetField()GetFields() 可以获取类型的一个或多个字段。

                Type type = typeof(Type);
                FieldInfo[] list = type.GetFields();
                foreach (var item in list)
                    Console.WriteLine(item.Name + "  |  " + item.FieldType + "    |   " + item.IsPublic);
    

    输出

    Delimiter  |  System.Char    |   True
    EmptyTypes  |  System.Type[]    |   True
    Missing  |  System.Object    |   True
    FilterAttribute  |  System.Reflection.MemberFilter    |   True
    FilterName  |  System.Reflection.MemberFilter    |   True
    FilterNameIgnoreCase  |  System.Reflection.MemberFilter    |   True
    

    这里有个问题,获取到的所有字段,都是 Public 的?

    到底是 Type 里面的字段都是 Public 的,还是反射只能获取到类型 Public 字段?

    我们通过实验验证一下。

    创建一个类

        public class MyClass
        {
            public string A { get; set; }
    
            // 不公开的属性,一般不会这样写
            private string B { get; set; }
    
            public string C;
            protected string D;
            internal string E;
            private string G;
        }
    

    打印

                Type type = typeof(MyClass);
    
                PropertyInfo[] listA = type.GetProperties();
                // 属性没有 item.IsPublic 等
                foreach (var item in listA)
                    Console.WriteLine(item.Name + "  |  " + item.PropertyType);
    
                Console.WriteLine("**************");
    
                IEnumerable<PropertyInfo> listB = type.GetRuntimeProperties();
                foreach (var item in listB)
                    Console.WriteLine(item.Name + "  |  " + item.PropertyType);
    
                Console.WriteLine("**************");
    
                FieldInfo[] listC = type.GetFields();
                foreach (var item in listC)
                    Console.WriteLine(item.Name + "  |  " + item.FieldType + "    |   " + item.IsPrivate + "    |   " + item.IsPublic);
    
                Console.WriteLine("**************");
    
                IEnumerable<FieldInfo> listD = type.GetRuntimeFields();
                foreach (var item in listD)
                    Console.WriteLine(item.Name + "  |  " + item.FieldType + "    |   " + item.IsPrivate + "    |   " + item.IsPublic);
    

    输出

    A  |  System.String
    **************
    A  |  System.String
    B  |  System.String
    **************
    C  |  System.String    |   False    |   True
    **************
    <A>k__BackingField  |  System.String    |   True    |   False
    <B>k__BackingField  |  System.String    |   True    |   False
    C  |  System.String    |   False    |   True
    D  |  System.String    |   False    |   False
    E  |  System.String    |   False    |   False
    G  |  System.String    |   True    |   False
    
    

    GetProperties()GetFields() 都只能获取到 public 类型的属性/字段;

    GetRuntimeProperties()GetRuntimeFields() ,能够获取所有的属性/字段;

    还有一个重要的地方,GetRuntimeFields() 获取到了 <A>k__BackingField<B>k__BackingField,这是因为 {get;set;}这样的属性,C# 会默认生成一个字段给他。

    1.2.4 方法

    通过 GetMethod()GetMethods() 可以获取到类型的 MethodInfo ,表示方法信息;

    MethodInfoConstructorInfo 非常相似,示例如下

                Type type = typeof(System.IO.File);
                MethodInfo[] list = type.GetMethods();
                foreach (var item in list)
                {
                    Console.WriteLine(item.Name + "   |   " + item.IsStatic + "   |   " + item.IsPublic);
                    ParameterInfo[] parms = item.GetParameters();
                    foreach (var itemNode in parms)
                    {
                        Console.WriteLine(itemNode.Name + "   |   " + itemNode.ParameterType + "    |   " + itemNode.DefaultValue);
                    }
                    Console.WriteLine("***********");
                }
    

    输出

    OpenText   |   True   |   True
    path   |   System.String    |
    ***********
    CreateText   |   True   |   True
    path   |   System.String    |
    ***********
    AppendText   |   True   |   True
    path   |   System.String    |
    ***********
    Copy   |   True   |   True
    sourceFileName   |   System.String    |
    destFileName   |   System.String    |
    ... ...
    

    参考资料地址:https://docs.microsoft.com/zh-cn/dotnet/api/system.reflection.methodinfo?view=netcore-3.1

    1.2.5 事件

    使用 GetEvent()GetEvents() 可以获取类型的事件列表,返回 EventInfo / EventInfo[] 类型。

    创建一个类型

        public class MyClass
        {
            public delegate void Test(int a,int b);
            public event Test TestHandler;
        }
    

    打印

                Type type = typeof(MyClass);
                EventInfo[] list = type.GetEvents();
                foreach (var item in list)
                {
                    Console.WriteLine(item.Name + "   |   " + item.EventHandlerType);
                }
    

    输出

    TestHandler   |   Mytest.MyClass+Test
    

    1.2.6 成员

    使用 GetMember()GetMembers() 获取类型的成员,返回 MemberInfo / MemberInfo[] 类型。

    简单来说,就是以上构造函数、属性、字段等的无差别集合体。

    创建一个类型

        public class MyClass
        {
            public delegate void Test(int a, int b);
            public event Test TestHandler;
    
            public MyClass(int a) { }
    
            public MyClass(int a, int b) { }
    
            public void TestMetod()
            {
            }
        }
    

    打印

                Type type = typeof(MyClass);
                MemberInfo[] list = type.GetMembers();
                foreach (var item in list)
                {
                    Console.WriteLine(item.Name + "   |   " + item.MemberType);
                }
    

    输出

    add_TestHandler   |   Method
    remove_TestHandler   |   Method
    TestMetod   |   Method
    GetType   |   Method
    ToString   |   Method
    Equals   |   Method
    GetHashCode   |   Method
    .ctor   |   Constructor
    .ctor   |   Constructor
    TestHandler   |   Event
    Test   |   NestedType
    

    此文仅授权《NCC 开源社区》订阅号发布

  • 相关阅读:
    怎么自定义修改CnBlogs博客园主题模板css样式
    前端怎么避免无效的请求,减轻服务器负载
    360浏览器奇葩问题:非得打开一次控制台才能登录(try catch finally 用法)
    react中<br/>不换行、多个&nbsp;只显示一个空格的问题 dangerouslySetInnerHTML
    webpack压缩文件错误:ERROR in bundle.js from UglifyJs
    webpack css单独打包 及extract-text-webpack-plugin插件
    css如何引入第三方字体
    计数排序
    接口
    抽象方法和抽象类
  • 原文地址:https://www.cnblogs.com/whuanle/p/12152660.html
Copyright © 2020-2023  润新知