当前位置: 首页 > 编程语言 > C#

如何在C#中实现反射?分享

时间:2023-04-11 00:01:44 C#

C#中如何实现反射?我很好奇Type.GetType()是在哪里实现的,所以我查看了程序集并注意到Type.GetType()调用了base.GetType()并且由于从MemberInfo继承了类型,我发现它被定义为_MemberInfo。GetType()返回this.GetType()。由于我找不到显示C#如何获取类型信息的实际代码,我想知道:CLR如何在运行时从对象中获取Type和MemberInfo?.NETFramework2.0的实际源代码可在此处获得(用于教育目的):http://www.microsoft.com/en-us/download/details.aspx?id=4917这是C#语言实现。你可以用7zip解压。您将在此处找到反射名称空间(相对):sscli20CL??RSRCBCLSYSTEM反射我正在深入研究您所询问的确切实现,但这是一个好的开始。更新:抱歉,但我认为这是一条死胡同。Type.GetType()调用来自System.Object的基本实现。如果您检查该代码文件(.sscli20clrsrcbclsystemobject.cs),您会发现该方法是extern(请参见下面的代码)。进一步检查可以揭示实现,但它不在BCL中。我怀疑它会在某处使用C++代码。//返回表示此对象实例的Type对象。//[MethodImplAttribute(MethodImplOptions.InternalCall)]publicexternTypeGetType();更新(再次):我深入挖掘并在CLR虚拟机本身的实现中找到了答案。(它在C++中)。第一个拼图在这里:sscli20CL??RSRC虚拟机ecall.cpp在这里我们看到将外部调用映射到C++函数的代码。FCFuncStart(gObjectFuncs)FCIntrinsic(“GetType”,ObjectNative::GetClass,CORINFO_INTRINSIC_Object_GetType)FCFuncElement(“InternalGetHashCode”,ObjectNative::GetHashCode)FCFuncElement(“InternalEquals”,ObjectNative::Equals)FCFuncEnd()现在,我们需要找到ObjectNative::GetClass……这里是:sscli20CL??RSRC虚拟机comobject.cpp这是GetType的现实:FCIMPL1(Object*,ObjectNative::GetClass,Object*pThis){CONTRACTL{THROWS;SO_TOLERANT;禁用(GC_TRIGGERS);//FCallCheck现在调用ForbidenGCINJECT_FAULT(FCThrow(kOutOfMemoryException););SO_TOLERANT;模式合作;}CONTRACTL_END;OBJECTREFobjRef=ObjectToOBJECTREF(pThis);OBJECTREFrefType=NULL;类型句柄typeHandle=TypeHandle();如果(objRef==NULL)FCThrow(kNullReferenceException);typeHandle=objRef->GetTypeHandle();如果(typeHandle.IsUnsharedMT())refType=typeHandle.AsMethodTable()->GetManagedClassObjectIfExists();否则refType=类型Handle.GetManagedClassObjectIfExists();如果(refType!=NULL)返回OBJECTREFToObject(refType);HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_2(Frame::FRAME_ATTR_RETURNOBJ,objRef,refType);如果(!objRef->IsThunking(Man))refType(Get)refType=CRemotingServices::GetClass(objRef);HELPER_METHOD_FRAME_END();返回OBJECTREFToObject(refType);}FCIMPLEND最后,GetTypeHandle的实现和其他一些支持函数可以在这里找到:sscli20CL??RSRCvirtualmachineobject.cppreflection最重要的部分作为CLI本身的一部分实现,因此您可以查看MSCLI参考源(也称为“转子”)或单声道源。但是:它主要是C/C++。公共API实现细节(MethodInfo、Type等)可能是C#。它可能不会直接回答你的问题。但是,这里简要概述了托管代码如何理解类型。每当编译代码时,编译器都会分析/解析源文件并收集它遇到的信息。例如,看看下面的类。A类{publicintProp1{get;privateset;}protectedboolMet2(floatinput){returntrue;}}编译器可以看出这是一个有两个成员的内部类。成员1是具有私有设置器的int类型的属性。成员2是一个名为Met2的布尔类型的受保护方法,它采用浮点输入(输入名称为“input”)。所以,它拥有所有这些信息。它将此信息存储在程序集中。有几张桌子。例如,类(类型)都在一个表中,而方法在另一个表中。考虑SQL表,尽管它们肯定不是。当用户(开发人员)想要了解有关类型的信息时,它会调用GetType方法。此方法依赖于对象指针类型的对象隐藏字段。这个对象基本上是一个指向类表的指针。每个类表都有一个指向方法表中第一个方法的指针。每个方法记录都有一个指向参数表中第一个参数的指针。PS:此机制是使.NET程序集更安全的关键。您不能替换指向方法的指针。它会破坏集合的签名。JIT编译也非常依赖于这些表正如@GlennFerrieLive所指出的,对GetType的调用是一个InternalCall,这意味着实现是在CLR本身中,而不是在任何BCL中。我的理解是CLR内部方法从这个指针获取运行时类型信息,基本等于类型的名字。然后它从所有加载的程序集(可能在当前AppDomain中)的元数据中查找完整的类型信息,这使得反射相当昂贵。元数据区域基本上是一个集合中所有类型和成员的数据库,它从中构造Type或Method|Property|FieldInfo的实例。以上就是C#学习教程:如何在C#中实现反射?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: