with what net method getfields done c# .net reflection encapsulation cil

net - what can be done with reflection in c#



¿Por qué el tipo System.__ ComObject reclama(a veces) ser público cuando no lo es? (1)

Solo una rareza que descubrí cuando estaba reflexionando sobre todos los tipos para comprobar algo más por curiosidad.

¿Por qué la clase System.__ComObject del ensamblado mscorlib.dll (a veces?) System.__ComObject ser pública cuando, de hecho, parece no ser pública? Si ejecuto el siguiente código en una aplicación de consola C # simple:

var t = Type.GetType("System.__ComObject"); Console.WriteLine(t.IsPublic); // "True" ?! Console.WriteLine(t.IsVisible); // "False"

La salida parece conflictiva. Un tipo no anidado ( t.IsNested es falso) debe dar el mismo valor de verdad para IsPublic e IsPublic . Cuando miro el montaje con IL DASM veo:

.class private auto ansi beforefieldinit System.__ComObject extends System.MarshalByRefObject { } // end of class System.__ComObject

que, para mí, se parece mucho a una clase no pública , algo que correspondería al código C # a continuación:

namespace System { // not public internal class __ComObject : MarshalByRefObject { ... } }

Cuando me comparo con otro tipo que tiene un nombre similar, System.__Canon y modificadores de IL similares, tanto IsPublic como IsPublic devuelven false como se esperaba.

¿Alguien sabe por qué (y cuándo) Type.GetType("System.__ComObject").IsPublic da verdad?


La implementación de Mono de __ComObject puede dar algunas pistas. De hecho, se declara como interno , pero los comentarios dicen "No tiene métodos públicos, su funcionalidad se expone a través de System.Runtime.InteropServices.Marshal " . No he buscado en Marshal , pero asumo que es responsable de la implementación de GetType() , por lo que también podría personalizar la propiedad de IsPublic .

En mi experiencia, Type.GetType("System.__ComObject").IsPublic siempre es true . Con respecto a GetType("System.Net.Mail.MSAdminBase") , creo que es una clase COM expuesta a través de un ensamblaje de interoperabilidad primario personalizado , donde la visibilidad de un tipo se puede controlar explícitamente (aunque es solo mi opinión, no se ha realizado ninguna investigación hecho).

[ACTUALIZAR]

IsPublic el último código fuente de Framework y descubrí que estaba equivocado al suponer que la personalización de la propiedad __ComObject para __ComObject Type la realiza Marshal . En realidad, se realiza mediante código no gestionado. Object.GetType() se define dentro de Object.cs de esta manera:

[MethodImplAttribute(MethodImplOptions.InternalCall)] public extern Type GetType();

El código fuente no administrado para su implementación en .NET 4.x no está disponible, pero está available para .NET 2.0. Hay una excelente respuesta sobre la implementación de Object.GetType en .NET 2.0. Acabo de agregar, IsPublic se define por la interfaz System.Runtime.InteropServices._Type que deriva System.Type , y puede ser reemplazado por cualquiera de las clases System.Type de System.Type . Aparentemente, una implementación de dicha clase es devuelta por Object.GetType , y eso sucede dentro de ObjectNative::GetClass (sscli20 / clr / src / vm / comobject.cpp), como se muestra en la respuesta :

if (!objRef->IsThunking()) refType = typeHandle.GetManagedClassObject(); else refType = CRemotingServices::GetClass(objRef);

Confirmo que el comportamiento de IsPublic depende de la versión de Framework. Probé el siguiente script de PowerShell en diferentes máquinas virtuales:

Write-Host ([System.Environment]::Version) ([Type]::GetType("System.__ComObject")).IsPublic

La salida es:

2.0.50727.3643 False (WinXP) 4.0.30319.18052 True (Win7) 4.0.30319.19079 True (Win8)

Aparentemente, ha cambiado de False a True desde .NET 2.0. Estoy de acuerdo en que True es inconsistente con la declaración de __ComObject ( internal class __ComObject ... ). Personalmente no veo ninguna razón para tal cambio, porque la única forma de obtener una instancia de __ComObject es a través de la interoperabilidad.