2013-08-06 1 views
20

그냥 이상한 일 내가 호기심에서 뭔가 다른 것을 확인하기 위해 모든 유형을 반성하는 것을 발견했을 때.왜 System .__ ComObject 유형이 (때로는) public이 아닌지 주장합니다.

mscorlib.dll (종종?)의 클래스 System.__ComObject은 실제로 그것이 비공개 인 것으로 보이는 경우 공개로 주장하는 이유는 무엇입니까? 간단한 C# 콘솔 응용 프로그램에서 다음 코드를 실행하면

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

출력이 충돌하는 것처럼 보입니다. 중첩되지 않은 유형 (t.IsNested이 false 인 경우)은 IsPublicIsVisible에 대해 동일한 진리 값을 제공해야합니다. 내가 IL DASM와 어셈블리를 볼 때 난을 참조하십시오

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

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

나에게, 대단히 비공개 클래스처럼 아래 C# 코드에 해당하는 무언가를 보이는,

내가 다른, System.__Canon을 비슷한 이름을 가진 유형 및 유사 IL 수정 비교, 예상대로 거짓 모두 IsPublicIsVisible 돌아갑니다. Type.GetType("System.__ComObject").IsPublic 사실 제공하는 이유 (때)

는 아는 사람 있나요? __ComObject

+1

시스템 .__ ComObject 및 System .__ Canon은 매우 다릅니다. 첫 번째는 COM 개체 (IsCOMObject == true)입니다. 이것이 내가 공용이라고 생각하는 이유입니다. –

+1

@Mihail'var t = typeof (Uri) .Assembly.GetType ("System.Net.Mail.MSAdminBase");''IsCOMObject'가 아니라'IsNotPublic' 인 또 다른 유형의't'가 있습니다. 이것은 어셈블리에 의존하지 않는 한 그 설명에 대한 "반례문"인 것처럼 보입니다 ('System.Net.Mail.MSAdminBase'는'System .__ ComObject'와 비교하여 다른 어셈블리에 있습니다). –

+1

내가 알아낼 수있는 것은 결함 일 수 있다는 것입니다! 나는 비슷한 물건들을 발견했는데, 너희들도 똑같이 나타 났을지도 모른다. [link] (http://microsoft.public.dotnet.framework.interop.narkive.com/06Y4MWuX/reflection-messing-up-the-type-hierarchy)를 따르십시오. – Nilesh

답변

10

Mono's implementation는 몇 가지 단서를 제공 할 수 있습니다. "그 기능은 저점 System.Runtime.InteropServices.Marshal을 노출, 그것은 공용 방법이 없다"그것은 참 내부로 선언되어 있지만 코멘트 말. 나는 Marshal을 파고 들지 않았지만, GetType()의 구현에 대한 책임이 있다고 가정하기 때문에 IsPublic 속성도 사용자 정의 할 수 있습니다. 내 경험에

Type.GetType("System.__ComObject").IsPublic 항상 true입니다. GetType("System.Net.Mail.MSAdminBase")에 대해서는 customized primary interop assembly을 통해 노출 된 COM 클래스라고 생각합니다. 유형의 가시성을 명시 적으로 제어 할 수 있습니다 (단, 내 생각이지만 연구가 수행되지 않았습니다).

[업데이트]

은 내가 latest Framework source code있어 내가 __ComObject 유형에 대한 IsPublic 재산의 정의가 Marshal에 의해 수행되는 것을 나의 가정에 대한 잘못을 발견했습니다. 사실 그것은 관리되지 않는 코드에 의해 수행됩니다.

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

.NET 4.x의의 구현에 대한 관리되지 않는 소스 코드를 사용할 수없는, 그러나 .NET 2.0 available입니다 : Object.GetType()은 다음과 같이 Object.cs 내에서 정의된다. .NET 2.0에는 구현에 대해 excellent answer이 구현되어 있습니다. 난 그냥 IsPublic가에서 파생 System.TypeSystem.Runtime.InteropServices._Type 인터페이스에 의해 정의되고, 추가 것, 그리고 System.Type -descendent 클래스의 오버라이드 (override) 할 수 있습니다. 외관상으로는, 그런 종류의 실시는 Object.GetType에 의해 돌려 보내지고 ObjectNative::GetClass (sscli20 \ clr \ src \ vm \ comobject) 안에 일어나고있다.CPP), the answer와 같이 내가 IsPublic의 동작은 Framework 버전에 따라 확인

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

.

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

출력은 다음과 같습니다 :

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

분명히, 그것은 .NET 2.0 이후 TrueFalse 변경된 나는 다른 가상 머신에서 다음 PowerShell에서 스크립트를 시도했다. True__ComObject (internal class __ComObject ...)의 선언과 일치하지 않습니다. 개인적으로 그러한 변경에 대한 이유는 없습니다. __ComObject의 인스턴스를 얻는 유일한 방법은 interop을 사용하기 때문입니다.

+0

Mono에서 테스트하지 않았습니다. 관련성이있는 것으로 링크 된 소스 코드에서 아무것도 찾지 못했습니다. 'GetType'과'IsPublic'에 관해서 당신이 무슨 말을 하려는지 모르겠습니다. 후자는 추상 System.Type 클래스의 가상 (인터페이스 구현 임에도 불구하고) 인스턴스 속성이므로,'__ComObject' 또는'Marshal'이 "사용자 정의 할 수있는"방법 (단어)에 대한 설명이 필요합니다. 질문에서 "(때로는)"라고 말한 이유는 두 대의 다른 컴퓨터에서 PowerShell을 통해 테스트 한 결과로, 한 대의 컴퓨터에서 (셸을 통해) '__ComObject'를 비공개로 처리한다는 것입니다. –

+1

내가 PowerShell을 다음 시도했다 :. '쓰기 호스트 ([System.Environment] :: 버전) ([유형] :: GetType을 ("시스템 .__하여 ComObject")) IsPublic', 출력 :'4.0.30319.19079 True' (Win8), '4.0.30319.18052 True' (Win7),'2.0.50727.3643 False' (WinXP). 분명히,'IsPublic'의'__ComObject'에 대한 결과는 프레임 워크 버전에 달려 있습니다. 나는 당신이 요청한'마샬 (Marshal) '에 대한 조사를하고 설명을 할 것입니다. – Noseratio

+0

죄송합니다, 나는 당신이 아닌 가상 _is 그 ('IsPublic') (인터페이스를 구현하지만) 추상'System.Type'에 인스턴스 property_ 말 무슨 뜻인지 모르겠어요. 이 속성은'System.Runtime.InteropServices._Type' 인터페이스에 정의되어 있으므로 정의에 의해 가상이며'IsCOMObject'와 마찬가지로 모든 파생 클래스에 의해 무시 될 수 있습니다. 'System.Type'은'IsPublic'을 구현하지 않지만, 파생 된 클래스 중 일부는 않습니다. 'System.RuntimeType'. 나는 사용자 정의가'Marshal '에 의해 수행된다고 가정 할 때 나는 틀렸다는 것을 인정한다. 실제로 그것은 관리되지 않는 코드로 수행된다. 내 대답을 더 자세히 업데이트했습니다. – Noseratio

관련 문제