在上一篇博文中,我知道反射原理,是通过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();
}
}
}
}
纸上得来终觉浅,绝知此事要躬行,为了票子,建议敲这些代码,感知,觉得会收获的,博主实际,精力,能力有限,
不足之处请多指正,共同交流学习,进步。