2014-10-16 4 views
0

클래스의 전체 구조를 반복해야합니다. 내 WCF 메서드로 보낸 개체를 조사하고 현재 각 클래스 및 모든 속성과 해당 값을 나열하는 ToString() 오버로드가 있습니다. 이 작품; 하드 코딩되어 있으므로 클래스에 속성을 추가 할 때마다 업데이트해야합니다.리플렉션 - 클래스 인 속성으로 반복 클래스

현재 솔루션은 VB이지만 다음 버전은 C#이므로 두 태그가 모두 사용됩니다.

클래스는 기본 유형으로 만 구성되거나 클래스가 다른 객체로 구성 될 수 있습니다. 간단한 클래스를 반복하는 것은 문제가되지 않습니다.

속성이 실제로 다른 클래스 인 경우 식별에 어려움이 있습니다. 아래 예제에서 약속과 환자를 반복하고 각각의 속성 값을 덤프 할 수 있습니다.

PatientAppointment을 통해 반복 시도 중입니다. 나는 MSDN과 같은 것을 샅샅이 조사하고 유형 내에서 무수한 속성을 시도했다.

Public Class PatientAppointment 
    Public Property Pat As Patient 
    Public Property Appt As Appointment 
End Class 

Public Class Appointment 
    Public Property ApptProp1 As String 
    Public Property ApptProp2 As Integer 
End Class 

Public Class Patient 
    Public Property PatProp1 As String 
    Public Property PatProp2 As Integer 
End Class 
+0

그리고 어떤 오류가 발생합니까? – BradleyDotNET

+1

'PatientAppointment'를 얼마나 정확하게 반복 하시겠습니까? 재귀 적으로 반복하고 싶습니까 ('PatientAppointment'의 각 속성과'Pat'와'Appt'의 각 속성을 반복합니다)? 아니면 속성이 클래스인지 여부를 알고 싶습니까? –

+0

- 오류가 표시되지 않습니다. –

답변

0

확실한 수준으로 유형을 식별 할 수있는 방법을 찾고있는 것 같습니다. 한 가지 방법은 리플렉션을 사용하여 찾기 쉽고 필터링 할 수있는 맞춤 속성을 사용하는 것입니다. 속성을 반복 할 때 볼 수있는 RealMcCoy 경우가로 드릴 필요가 원하는/한 경우

Public Class RealMcCoy 
    Inherits Attribute 

    Public Property IsReal As Boolean 

    Public Sub New(b as Boolean) 
     IsReal = b 
    End Sub 
End Class 

<RealMcCoy(True)>  
Public Class Patient 
    ... 
End Class 

<RealMcCoy(True)> 
Public Class Appointment 
    ... 
End Class 

지금 확인합니다. 속성은 유형에있을 것입니다 때문에, 거기에 추가 단계는 각 속성의 유형을 얻을 당신이 유형을 추가하고 속성을 추가 해달라고하면 그것은 나누기

Dim props As PropertyInfo() = myFoo.GetType.GetProperties 
    Dim pt As Type 

    For Each pi As PropertyInfo In props 
     pt = pi.PropertyType   ' get the property type 

     Dim attr() As RealMcCoy = 
       DirectCast(pt.GetCustomAttributes(GetType(RealMcCoy), True), RealMcCoy()) 
     If attr.Length > 0 Then 
      ' bingo, baby...optional extra test: 
      If attr(0).IsReal Then 
       Console.Beep() 
      End If 
     Else 
      ' skip this prop - its not a real mccoy 
     End If 
    Next 
End Sub 

것을 폴링이지만,보다 깨지기 각 Types를 해당 구성 속성으로 업데이트해야합니다. 위조 된 인터페이스는 질의하기 쉽지만 동일한 단점이 있습니다.

"게임"문제에 대해 잘 모르겠습니다 - 다른 유형이 선택 될까봐 걱정됩니까? 애트리뷰트는 어셈블리로 컴파일되기 때문에 "게임하기"어려울 것입니다. 위의 코드는 bool보다는 GUID (어쩌면 어셈블리에 첨부 된 것일 수도 있습니다)를 반환하는 데 사용할 수 있습니다.

절대 확실성을 찾기가 어려울 것입니다.


RealMcCoy 속성

아마 다른 유형의 속성으로 사용되는 최상위 수준의 유형 ( PatientAppointment) 단지 종류 (클래스)에 적용되지 않습니다. 객체는이를 쉽게 식별 할 수있는 방법입니다.

사용 방법에 따라 TypeName-PropertyName 쌍의 사전 또는 해시 테이블 이미이 RealMcCoys으로 식별되어 유용 할 수 있으므로 전체 반사 프로세스가 단락 될 수 있습니다. 즉석에서 추가하기보다는 shown in this answer으로 전체 목록을 작성할 수 있습니다 (RangeManager.BuildPropMap 절차 참조).

실제로 상속을 어딘가에서 사용하고자 할 수도 있으므로 상속 접근법에 대해서는 확신 할 수 없습니다. 인터페이스가 더 잘 작동 할 수도 있습니다. 처음에는 단순한 존재가 시작시 트리거가 될 수 있지만 서비스를 제공하는 데 사용될 수도 있습니다.


간단한 테스트 케이스 :

' B and C classes are not tagged 
Friend Class FooBar 
    Public Property Prop1 As PropA 
    Public Property Prop2 As PropB 
    Public Property Prop3 As PropC 
    Public Property Prop4 As PropD 
    Public Property Prop5 As PropE 
End Class 

루프의에 행을 추가

Dim f As New FooBar 
' use instance: 
Dim props As PropertyInfo() = f.GetType.GetProperties 
Dim pt As Type 

For Each pi As PropertyInfo In props 
    pt = pi.PropertyType 

    Dim attr() As RealMcCoy = 
      DirectCast(pt.GetCustomAttributes(GetType(RealMcCoy), True), RealMcCoy()) 

    Console.WriteLine("Prop Name: {0}, prop type: {1}, IsRealMcCoy? {2}", 
      pi.Name, pt.Name, If(attr.Length > 0, "YES!", "no")) 
Next 

출력 : Plutonix에

Prop Name: Prop1 prop type: PropA IsRealMcCoy? YES! 
Prop Name: Prop2 prop type: PropB IsRealMcCoy? no 
Prop Name: Prop3 prop type: PropC IsRealMcCoy? no 
Prop Name: Prop4 prop type: PropD IsRealMcCoy? YES! 
Prop Name: Prop5 prop type: PropE IsRealMcCoy? YES! 
+0

또 다른 방법은 모든 단일 클래스를 'McCoy' 기본 클래스에서 상속 받고 단순히'IsAssignableFrom'을 신호로 사용하는지 확인하는 것입니다. – Plutonix

+0

안녕하세요 Plutonix, 지금 이걸 가지고 놀고 있습니다. 또한 IsAssignableFrom 아이디어가 마음에 든다. 그리고이 버전의 여러 클래스에서 상속받을 계획이므로 C# 버전에서이 아이디어를 사용할 수있다. 어쨌든, 샘플에 대해 질문이 있습니다. dim attr()을 mccoy로 말할 때, mccoy는 실제로 무엇이되어야합니까? 나는 realmccoy를 시도했지만 attr()에 대한 빈 목록을 얻고있다. –

+0

나는 'RealMcCoy'이어야한다. 나는'RealMcCoy.IsRealMcCoy'를 피하려고 노력하고 있었고, 약간의 문자들을 버렸다. 분명히 attr을 갖지 않는 * 유형의 많은 소도기가있을 것입니다. 그러나 그것을 가지고있는 것은 나타나야합니다. 그것이 작동중인/테스트 된 코드입니다 (현재). – Plutonix

0

많은 감사합니다! 여기 내 마지막 기능입니다. 만약 내 대답이 Plutonix의 대답을 대체한다면, 나는이 점을 충분히 깨닫기에 충분할만큼 이것을 조정할 필요가있다.

중첩 된 유형의 8 단계로 테스트했습니다. 이것이 프로토 타입이기 때문에 기본 예외 처리.

Function IterateClass(ByVal o As Object, ByVal topLevelFlag As Boolean, ByVal indentLevel As Integer) As String 

    Dim retVal As New StringBuilder 

    Try 

     '' Iterate top level of supplied type '' 
     '' Query each property for custom attribute ADMICompositeClassAttribute '' 
     '' If exists and set to true then we're dealing with a base class that we need to break down recursively '' 
     '' If not then immediately dump this type's properties '' 


     '' Build header of output '' 
     If topLevelFlag Then 

      '' <<EXCERPTED>> '' 

     End If 


     '' We start walking through the hierarchy here, no matter how much we recurse we still need to do this each time '' 
     Dim properties_info As PropertyInfo() 
     properties_info = o.GetType().GetProperties() 

     For Each p As PropertyInfo In properties_info 
      Dim propName As String = p.Name 
      Dim propTypeList As List(Of String) = p.PropertyType.ToString().Split(".").ToList() 
      Dim propType As String = propTypeList(propTypeList.Count - 1).Replace("[", "").Replace("]", "") 
      Dim pValue As Object = Nothing 

      '' We check this type for custom attribute ADMICompositeClassAttribute '' 
      '' Is this type a composite? '' 
      Dim oAttr() As ADMICompositeClassAttribute = p.PropertyType.GetCustomAttributes(GetType(ADMICompositeClassAttribute), False) 
      Dim indentString As String = String.Concat(Enumerable.Repeat(" ", indentLevel)) 
      If oAttr.Length > 0 AndAlso oAttr(0).IsComposite Then 

       '' This is a nested type, recurse it '' 
       Dim dynType As Type = p.PropertyType() 
       Dim dynObj As Object = Activator.CreateInstance(dynType) 

       '' <<EXCERPTED '' 

      Else 

       pValue = p.GetValue(o, Nothing) 

      End If 

     Next 


    Catch ex As Exception 
     retVal.AppendLine(ex.ToString()) 

    End Try 
    Return retVal.ToString() 


End Function 
관련 문제