C# 反射高阶语法

 

在上一篇博文中,我知道反射原理,是通过metadata元数据,拿到各种类型对象,这一篇博文重点列出,常见语法:

知识点:

第一:获取type对象,三种方式,即typeof运算符,静态GetType,程序Assembly对象的GetType方法

第二:获取Type对象各种其他Type对象,比如数组Type对象中子元素对象Type,GetElementType()

第三:获取Type类型中嵌套类型对象,比如类中定义的类,它是非递归,并且获取公开访问属性的嵌套类

第四:获取Type对象的全名称,即命名空间+名称,封闭类型的Type有些不同,列出泛型参数名称

另外嵌套类型Type对象,名称会+外面包括名称

第五:获取基类即接口的各种Type对象,

第六:返回判断关系,即某个实例是否是Type对象的一个实例,

type.IsInstanceOfType(instance)

 注意://of关键是实际上当前Type的实例,所以像下面使用,
            //同理就是,from,是否从当前实例分配,不要弄反调用对象和传入参数对象

baseType.IsAssignbleFrom(deseveType)

第七:得到类型对象的Type对象,即可获取该对象各种信息,比如字段,属性等等信息

第八:借助Type创建类型对应的实例对象,

及三种方式性能比较:new CreateInstance Invoke

new方法,执行时间:15ms,垃圾回收次数:6
CreateInstance方法,执行时间:1899ms,垃圾回收次数:85
ConstructionInfo的Invoke方法,执行时间:430ms,垃圾回收次数:16

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ReflectionDemo
{
    class BaseClass {
        public int BaseField = 0;
    }
    class DeriveClass : BaseClass {
        int DeriveField = 2;
        public string str;
    }

    public class People { 
    }
    public class Teacher:People {
        //无法自定义构造函数的泛型,
        //public Teacher(string t) { 
        //}
        class Son : People {
            class PlayTool { 

            }
        }
        public class Pet : People
        {
           
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //*************************第一个知识点:获取Type对象,常用方法有三种
            //A typeof() 需要对象名称
            Type deriveType = typeof(DeriveClass);
            //B Object的GetType()方法,需要生成一个对象
            Type deriveType2 =new DeriveClass().GetType();
            //通过程序集
            //这个返回的是当前类的对象类型
            Type deriveType3= Assembly.GetExecutingAssembly().GetType();
            Type deriveType33 = Assembly.GetExecutingAssembly().GetType("ReflectionDemo.Program");
            //获取当前运行的程序集中,定义的所有的类型
            Type[] deriveType333 = Assembly.GetExecutingAssembly().GetTypes();

            //**********************第二个知识点:获取对象里面包含,引用的Type对象,GetElementType
            Type stringArr = typeof(string).MakeArrayType(2);//创建一个二维数组类型
            //可以获取里面元素对象类型,还可以获取维数:
            int rank=stringArr.GetArrayRank();
            Type elementType = stringArr.GetElementType();
            Type refType= typeof(string).MakeByRefType();

            //************************第三个知识点:获取嵌套类型Type对象,Get
            //重点是,它获取的是公共类型的嵌套子类,非递归寻找所有子类
            Type teacherType = typeof(Teacher);
            Type[] nestedArr= teacherType.GetNestedTypes();


            //**********************第四个知识点:获取类型名称,一般类型,泛型类型,开放类型,封闭类型
            //*********Namespace+Name=FullName,但是获取嵌套类型的比如Pet,以及泛型类型,有些不同
            Type genericOpenType = typeof(List<>);
            //{Name = "List`1" FullName = "System.Collections.Generic.List`1"}
            Type genericCloseType = typeof(List<string>);
            //获取嵌套类型,不能直接typeof得到,
            //Type genericOpenType = new Teacher().;
            /*{Name = "List`1" FullName = "System.Collections.Generic.List`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"}*/
            // Namespace :System.Collections.Generic.List
            //总结,关于泛型全名称List'1后面数字表示泛型参数个数,
            //ReflectionDemo.Teacher+Pet
            Type neatedType = teacherType.GetNestedTypes()[0];

            ****************第五个知识点:获取基类,及接口类型
            ///获取基类,
            ///
            Type baseType = teacherType.BaseType;
            //哪一个字段继承好几个接口呢,
            Type[] interfacesType = typeof(List<>).GetInterfaces();
            //接口有很多

            //***************第六个知识点:IsInstanceOfType 和Is 功能相似,和IsAssignedFrom()功能相反
            bool selftbool=baseType.IsAssignableFrom(baseType);           
            //这个不是类型关系,比较的是是否是Type的实例,参数为object
            Teacher teacher = new Teacher();
            //of实际上当前Type的实例,所以像下面使用
            //同理就是,from,是否从当前实例分配
            //bool deserveType = teacherType.IsAssignableFrom(baseType);
            bool deserveType = baseType.IsAssignableFrom(teacherType);
            bool deservebool = teacherType.IsInstanceOfType(teacher);
           

            //***********************第七个知识点:遍历所有字段,

            //FieldInfo[] fields = deriveType.GetFields(BindingFlags.Public
            // | BindingFlags.Instance);
            foreach (FieldInfo item in deriveType.GetFields())
            {
                //不能是BaseClass对象中的值,有些字段不是,
                //如果是静态类型,GetValue(null)即可
                Console.WriteLine($"字段名称:{item.Name},字段值:{item.GetValue(new DeriveClass())},字段对象类型Type,{item.FieldType}");
            }
            FieldInfo[] fileInfos= deriveType.GetFields();

 //***************第八个知识点:通过Type实例化类型,方法
            // Activity.CreateInstance方法,本质是调用构造函数方法,构造函数,方法里面
            //也是生成一个类的数据结构,
            //因为没有重写默认构造函数,因此可以不用赋值,如果重写构造函数,没有赋值,将会报错
            Teacher teacherInstance =(Teacher)Activator.CreateInstance(teacherType,null);
            Teacher teacherInstance2 = (Teacher)Activator.CreateInstance(teacherType);
            //关于DateTime也是有构造函数,参考https://docs.microsoft.com/zh-cn/dotnet/api/system.datetime.-ctor?view=netcore-3.1
            //参数可以分别设置年月日
        }
    }
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace TypeRefectionDemo2
{
    public class InvokeClass
    {
        private string _testString;
        private long _testInt;

        public InvokeClass(string abc)
        {
            _testString = abc;
        }
        public InvokeClass(StringBuilder abc)
        {
            _testString = abc.ToString();
        }

        public InvokeClass(string abc, long def)
        {
            _testString = abc;
            _testInt = def;
        }
    }
    class Program
    {
        /*若要创建没有实例构造函数的值类型的实例,请使用 CreateInstance 方法。*/
        static void Main(string[] args)
        {
            InvokeClass invokeClass = new InvokeClass("");
            //不清楚如何调用构造函数
            //InvokeClass invokeClass2 = new InvokeClass(null);
            //无法根据指定构造函数,
            InvokeClass icc=(InvokeClass)Activator.CreateInstance(typeof(InvokeClass),"");
            //未找到对应的函数
            //InvokeClass icc2 = (InvokeClass)Activator.CreateInstance(typeof(InvokeClass), null);
            //另外一种方式,是通过获取构造函数信息对象,执行Invoke方法,来生成对象,
            ConstructorInfo[] constructorInfos = typeof(InvokeClass).GetConstructors();
            //获取指定的构造函数,比如两个参数,
            //这里数组本身并没有提供Find之类的方法,
            //借助静态类Array之中的方法FindAll所有符合条件,Find找到合适的一个
            ConstructorInfo[]  params2=Array.FindAll<ConstructorInfo>(constructorInfos,x=>x.GetParameters().Length==2);
            //仍然是得到参数列表,
            ConstructorInfo param2 = Array.Find<ConstructorInfo>(params2,x=>x.GetParameters()[1].ParameterType==typeof(long));
            //InvokeClass invokeclasss=(InvokeClass)params2[0].Invoke(new object[] { "",234});
            InvokeClass invokeclasss = (InvokeClass)param2.Invoke(new object[] { "",234});
            //constructorInfos.fin
            //若要创建没有实例构造函数的值类型的实例,请使用 CreateInstance 方法。
            //比较性能100万次比较

            using (new TestGC("new方法"))
            {
                InvokeClass iss;
                for (int i = 0; i < 1000000; i++)
                {
                    iss = new InvokeClass("");
                }
                iss = null;
            }

            using (new TestGC("CreateInstance方法"))
            {
                InvokeClass iss;
                for (int i = 0; i < 1000000; i++)
                {
                    iss = (InvokeClass)Activator.CreateInstance(typeof(InvokeClass),"");
                }
                iss = null;
            }

            using (new TestGC("ConstructionInfo的Invoke方法"))
            {
                InvokeClass iss;
                ConstructorInfo[] constructors= typeof(InvokeClass).GetConstructors();
                for (int i = 0; i < 1000000; i++)
                {
                    iss = (InvokeClass)constructors[0].Invoke(new object[] { ""});
                }
                iss = null;
            }
            /*new方法,执行时间:15ms,垃圾回收次数:6
CreateInstance方法,执行时间:1899ms,垃圾回收次数:85
ConstructionInfo的Invoke方法,执行时间:430ms,垃圾回收次数:16*/
        }

        internal sealed class TestGC : IDisposable
        {
            private Stopwatch sw = new Stopwatch();
            private string text;
            private int count;

            //构造开始便进行一次重置
            public TestGC(string t)
            {
                PrepareForOperation();
                text = t;
                //同时统计一次垃圾回收次数:
                count = GC.CollectionCount(0);
                //时间重新开始计时
                sw.Start();
            }
            //using内容结束时,释放资源,统计垃圾回收次数
            public void Dispose()
            {
                Console.WriteLine("{0},执行时间:{1}ms,垃圾回收次数:{2}", text, sw.ElapsedMilliseconds, GC.CollectionCount(0) - count);
            }

            ///相当于进行垃圾回收重置操作,即先垃圾回收上一次遗留,并确保完成
            ///并重新开始垃圾回收
            private static void PrepareForOperation()
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
            }
        }
        
    }
}

 

纸上得来终觉浅,绝知此事要躬行,为了票子,建议敲这些代码,感知,觉得会收获的,博主实际,精力,能力有限,

不足之处请多指正,共同交流学习,进步。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值