2009-08-28 5 views
17

리플렉션을 사용하여 아래 코드와 같은 일부 개체 속성을 덤프하는 루틴에서이 오류가 발생합니다.Type.IsGenericParameter가 참인 Type에서만 메서드를 호출 할 수 있습니다.

MemberInfo[] members = obj.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance) ; 

foreach (MemberInfo m in members) 
{ 
    PropertyInfo p = m as PropertyInfo; 
    if (p != null) 
    { 
     object po = p.GetValue(obj, null); 

     ... 
    } 
} 

실제 에러는 "단 Type.IsGenericParameter 해당하는 해당하는 유형이라고 할 수있다 방법."의 내부 예외 "호출 대상이 예외가 발생 된" 디버거 OBJ이 단계에서

가 표시 OBJ가 타입 System.RuntimeType

있어서의 m은 {}이다 System.Reflection.MethodBase DeclaringMethod

참고로

{Name = "SqlConnection" FullName = "System.Data.SqlClient.SqlConnection"} 

로서 (System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance) typeof (System.Data.SqlClient.SqlConnection) typeof (System.Reflection.BindingFlags.Instance) 만 65를 반환하는 반면에 System.RuntimeType 형식의 멤버는 188 개 항목을 포함합니다.

obj와 p.PropertyType에서 모두 isGenericParameter를 검사하려고 시도했지만, p.GetValue가 작동하는 대부분의 속성에 대해서는 false 인 것으로 보입니다.

정확히 "Type.IsGenericParameter가 참인 유형"이고 더 중요한 것은 시도/catch없이이 오류가 발생하지 않도록하려면 어떻게해야합니까? 우리가 T 포착되지 않은 즉, -

답변

13

, 당신은에서 변경 한 잘못된 가정, 즉 당신은 그 가정을이라고 가정했습니다.은 System.Data.SqlClient.SqlConnection 인스턴스의 멤버를 반환했지만 그렇지 않은 인스턴스는 반환했습니다. 반환 된 것은 System.Type 인스턴스의 멤버입니다. DeclaringType에 대한 MSDN 문서에서

:

누구 IsGenericParameter 재산 거짓 인 InvalidOperationException을 발생 유형에 DeclaringMethod 특성 얻기.

이렇게 ... InvalidOperationException이 던져지고있는 것을 이해할 수 있습니다. 자연스럽게 여기 열린 일반 유형을 다루지 않기 때문입니다. 열린 일반 유형에 대한 설명은 Marc Gravells answer을 참조하십시오.

+2

나는 빛을 볼 생각입니다 . p.GetValue는 'Type.IsGenericParameter가 참인 Type에 대해서만 호출 할 수 있습니다'라는 것이 아니라 p로 표시되는 기본 속성 (이 경우 DeclaringMethod)이 호출 될 수 있다는 것을 말하는 것은 아닙니다. Type.IsGenericParameter is 참된. – sgmoore

+1

정확히 "호출 대상에 의해 예외가 발생했습니다"는 의미입니다.이 경우 "호출 대상"은 DeclaringMethod 속성 가져 오기 도구이며, 읽음으로써 동일한 IsGenericParameter 예외가 발생합니다 'obj.DeclaringMethod'를 직접 호출하십시오. – stevemegson

+0

나는 이것이 가장 도움이 되었기 때문에이 대답을 필자의 받아 들인 대답으로 표시했다. 그러나 진실로 대부분의 다른 답변들도 도움이되었다. 그래서 모두에게 감사합니다. – sgmoore

13

그래서 정확히 열린 제네릭 형식의 제네릭 형식 인수 의미

는 "Type.IsGenericParameter이 true 인 유형"무엇 아직; 예 :

그래서; 너는 열려있는 제네릭을 주변에두고 있니? 아마도 obj을 어디서 얻었는지에 대한 예를 들려 줄 수 있을까요?

+0

OP는 obj의 System.RuntimeType – AnthonyWJones

+0

을 볼 수 있습니다. 문제는 오픈 제네릭의 존재가 아니라 일반적인 유형의 존재입니다. –

+0

예외로 시작합니다. (이 경우 SqlException)을 내 덤프 루틴에 전달합니다. 덤프 루틴은 순환 적이므로 예외의 모든 특성 및 필드에서 덤프가 호출됩니다. 제 코드에는 제네릭이 있지만 오픈 제네릭은 없습니다. 나를 혼란스럽게하는 이유는 p.GetValue가 명백히 사실이 아닌 GenericParameter가 true 인 경우에만 작동한다고 말하는 것 같습니다. – sgmoore

3

모든 단서가 있습니다. obj의 타입은 Type 클래스 자체 (또는 이상한 RuntimeType 미분)입니다.

오류가 발생하면 이라는 Type 클래스 속성이 반복됩니다. 그러나 Type 클래스의이 인스턴스가 설명하는 형식은 메서드의 일반 형식이 아닌 System.Data.SqlClient.SqlConnection입니다.

따라서 DeclaringMethod에서 get을 호출하면 예외가 발생합니다.

키의 종류는 Type입니다. 그것의 조금 원형지만 생각 : -

SqlConnection s = new SqlConnection(); 
Type t = s.GetType() 
Type ouch = t.GetType() 

설명 클래스는 무엇입니까?

1

시도/catch없이이 오류를 방지하려면 어떻게합니까?

거의 확실하게 할 수 없습니다.p.GetValue을 호출하면 해당 속성에서 getter를 호출하므로 예외가 발생할 수 있습니다. 예를 들어, SqlConnection.ServerVersion은 연결이 닫히고 예외를 처리해야하는 경우 예외를 throw합니다.

추가 구성원은 어디에서오고 있습니까?

당신의 obj 이미 SqlConnection를 나타내는 RuntimeType 객체보다는 SqlConnection의 인스턴스가 포함되어 있습니다. obj.GetMembers()SqlConnection 클래스의 65 명의 멤버를 반환하지만 GetType()을 다시 호출하면 RuntimeType의 188 멤버를 얻을 수 있습니다.

IsGenericParameter은 무엇입니까?

대신 클래스를 나타내는, 당신은 클래스 나 메소드 (List<T>.ConvertAll<TOutput>TTOutput에 대한 일반적인 매개 변수를 나타냅니다 RuntimeType의 인스턴스를 가질 수 있습니다.이 경우, TOutput를 나타내는 객체에 DeclaringMethod 당신이하자 것 RuntimeType가 클래스를 나타내는 경우 ConvertAll<> 방법을 나타내는 MethodInfo 객체. 그러나,하는 선언 방법의 아이디어가 이해되지 않는다. 속성을 읽는 것은 당신이 본 예외가 발생하는 이유입니다. 첫째

관련 문제