Jep*_*sen 20 .net c# reflection encapsulation cil
只是奇怪的是,当我反思所有类型时,我偶然发现了好奇心来检查其他东西.
为什么System.__ComObject
集会的阶级mscorlib.dll
(有时?)声称是公开的,而事实上它似乎是非公开的?如果我在一个简单的C#控制台应用程序中运行以下代码:
var t = Type.GetType("System.__ComObject");
Console.WriteLine(t.IsPublic); // "True" ?!
Console.WriteLine(t.IsVisible); // "False"
Run Code Online (Sandbox Code Playgroud)
输出似乎有冲突.非嵌套类型(t.IsNested
为false)应为IsPublic
和提供相同的真值IsVisible
.当我看到装配时,IL DASM
我看到:
.class private auto ansi beforefieldinit System.__ComObject
extends System.MarshalByRefObject
{
} // end of class System.__ComObject
Run Code Online (Sandbox Code Playgroud)
对我来说,它看起来非常像非公开类,这些对应于下面的C#代码:
namespace System
{
// not public
internal class __ComObject : MarshalByRefObject
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
当我比较其他类型的具有类似的名称,System.__Canon
以及类似IL改性剂,既IsPublic
与IsVisible
预期返回false.
有谁知道为什么(和什么时候)Type.GetType("System.__ComObject").IsPublic
给出了真实的?
nos*_*tio 10
Mono的实现的__ComObject
可能提供一些线索.它确实被宣布为内部,但评论说"它没有公开的方法,它的功能暴露在低谷System.Runtime.InteropServices.Marshal
".我没有挖Marshal
,但我认为它负责实施GetType()
,所以它也可以定制IsPublic
属性.
根据我的经验,Type.GetType("System.__ComObject").IsPublic
总是如此true
.关于GetType("System.Net.Mail.MSAdminBase")
,我相信它是通过定制的主互操作程序集暴露的COM类,其中可以明确控制类型的可见性(虽然这只是我的想法,没有进行过研究).
[UPDATE]
我有最新的Framework源代码,发现我错误地假设我IsPublic
的__ComObject
类型的属性定制是由Marshal
.实际上,它是由非托管代码完成的.Object.GetType()
在Object.cs中定义如下:
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern Type GetType();
Run Code Online (Sandbox Code Playgroud)
在.NET 4.x中实现它的非托管源代码不可用,但它可用于.NET 2.0.关于.NET 2.0中的实现,有一个很好的答案Object.GetType
.我只是添加,IsPublic
是由派生定义的System.Runtime.InteropServices._Type
接口定义的System.Type
,并且可以被任何System.Type
-descendent类覆盖.显然,这样的类的实现是通过返回Object.GetType
,这是怎么回事内ObjectNative::GetClass
(sscli20\CLR\SRC \虚拟机\ comobject.cpp),如图答案:
if (!objRef->IsThunking())
refType = typeHandle.GetManagedClassObject();
else
refType = CRemotingServices::GetClass(objRef);
Run Code Online (Sandbox Code Playgroud)
我确认行为IsPublic
取决于Framework版本.我在不同的VM中尝试了以下PowerShell脚本:
Write-Host ([System.Environment]::Version) ([Type]::GetType("System.__ComObject")).IsPublic
Run Code Online (Sandbox Code Playgroud)
输出是:
2.0.50727.3643 False (WinXP)
4.0.30319.18052 True (Win7)
4.0.30319.19079 True (Win8)
Run Code Online (Sandbox Code Playgroud)
显然,它已经从False
以True
自.NET 2.0.我同意这True
与__ComObject
(internal class __ComObject ...
)的声明不一致.我个人认为没有理由进行这样的改变,因为获得实例的唯一方法__ComObject
是通过互操作.