2015-01-21 3 views
2

클래스의 개체 (필드)를 반복하고 각 개체에서 메서드를 호출하려고합니다. 각 객체는 다른 유형입니다.VB 클래스 인스턴스에서 FieldInfo가 아닌 필드 개체 ​​가져 오기

여기
Public Class MySettings 
    Public IdentifyByFacType As RadioButtonSetting 

    Public WtrFacTypes As ListSetting 
    Public OilFacTypes As ListSetting 

    Public GroupByRef As CheckboxSetting 
    Public GroupRefAttr As TxtboxSetting 
End Class 

서브 객체 클래스들 중 하나의 부분이다 : 여기서 상위 클래스 인

<Serializable> 
Public Class TxtboxSetting 
    <XmlIgnore()> 
    Public MyControl As Windows.Forms.TextBox 
    <XmlIgnore()> 
    Public DefaultSetting As String 

    Private _SavedSetting As String 

    Public Property SavedSetting As String 
     Get 
      Return _SavedSetting 
     End Get 
     Set(value As String) 
      _SavedSetting = value 
      CurrentValue = value 
     End Set 
    End Property 

    Public Sub New() 
    End Sub 

    Public Sub New(DefaultSetting As String, MyControl As Windows.Forms.TextBox) 
     Me.DefaultSetting = DefaultSetting 
     Me.MyControl = MyControl 
    End Sub 

    Public Sub RestoreDefault() 
     CurrentValue = DefaultSetting 
    End Sub 
End Class 

MySettings 클래스의 서브 - 객체의 모든 예 GroupRefAttr 마찬가지로이 동일한 메소드 및 특성이지만 내부 코드는 다릅니다.

그래서 나는 MySettings 클래스와 같은 여러 클래스를 가지며, 각각은 다른 하위 오브젝트를 가질 것입니다. 이러한 클래스의 인스턴스가 주어지면 필드를 자동으로 반복하고 각 메서드에 RestoreDefault 메서드를 호출하려고합니다. MySettings 클래스에 어떤 객체가 있는지 알고 싶지 않습니다. 오히려, 그들 모두가 RestoreDefault 메소드를 가지고 있다는 것을 알기 때문에, 나는 각 객체에 대해 메소드를 호출하기 만하면됩니다.

많은 검색에도 불구하고이 작업을 수행 할 방법을 찾지 못했습니다. 반사로, 나는 단지 여기까지 얻을 수 있습니다 :

Dim Opts as New MySettings 
For Each var In Opts.GetType.GetFields 
    Dim RestoreDefault As System.Reflection.MethodInfo = var.FieldType.GetMethod("RestoreDefault") 
    RestoreDefault.Invoke(Opts, Nothing) 
Next 

그러나, 라인 RestoreDefault.Invoke(Opts, Nothing)에, 난 그냥 Opts에 전달할 수 없습니다, 내가하지 Opts, Opts의 필드 자체를 취급하고있다. 이 같은 진술은 작동합니다 : RestoreDefault.Invoke(Opts.GroupRefAttr, Nothing),하지만 그게 내가 먼저 MySettings 클래스에있는 객체를 알아야하고, 그 목적을 이깁니다. 런타임에 필드 인스턴스 객체를 잡고이를 제거하는 방법이 있습니까?

답변

0

RestoreDefault 메서드를 호출 할 때 설정이 포함 된 클래스가 아닌 설정 (즉, 필드 값)에서 호출해야합니다. 여기에 코드를 변경하면 문제를 해결해야합니다

Dim Opts as New MySettings 
For Each var In Opts.GetType.GetFields 
    Dim setting As Object = var.GetValue(Opts) 
    Dim RestoreDefault As System.Reflection.MethodInfo = var.FieldType.GetMethod("RestoreDefault") 
    RestoreDefault.Invoke(setting, Nothing) 
Next 

을하지만, 당신이 기본 클래스 또는 반사의 일부 또는 전부를 제거 할 수 있어야 인터페이스 중 하나를 소개합니다. 컨테이너 설정 클래스는 각각 RestoreDefault 메소드를 가진 공유 기본 클래스 또는 인터페이스를 갖는 일련의 설정을 가질 수 있습니다. 컨테이너 설정 클래스는 리플렉션을 사용하지 않고 기본 클래스 또는 인터페이스를 통해이 메소드를 호출합니다.

기본 클래스 :

Public MustInherit Class BaseSetting 
    Public MustOverride Sub RestoreDefault 
End Class 

특정 설정 클래스 :

Public Class TxtboxSetting 
    Inherits BaseSetting 

    Public Overrides Sub RestoreDefault() 
     ' Specific implementation 
    End Sub 
End Class 

BaseSetting에서 모든 클래스의 유도에 지금 반사를 사용하지 않고 RestoreDefault 메서드를 호출 할 수 있습니다.

그러나 디자인을 고려하면 반사를 사용하여 MySettings 클래스의 containsd 설정을 가져올 수 있습니다. 당신은 이런 식으로 작업을 수행 할 수 있습니다

Dim settings = From fieldInfo in Opts.GetType.GetFields 
       Where GetType(BaseSetting).IsAssignableFrom(fieldInfo.FieldType) 
       Select DirectCast(fieldInfo.GetValue(Opts), BaseSetting) 
For Each setting In settings 
    setting.RestoreDefault() 
Next 

반영 BaseSetting에서 파생 모든 필드를 찾는 데 사용 된 후 RestoreDefault은 각 필드에 호출된다. 이 메서드는 문자열이 나타내는 RestoreDefault 메서드의 이름에 따라 코드가 달라지는 "마법 문자열"문제가 발생하지 않습니다.

(또한, 호출 MySettingsMySettings에서 상속 아무것도 없기 때문에 부모 조금 잘못된 것입니다. 대신이 클래스가 다른 설정을 포함하는 클래스입니다.)

+0

이렇게하면 문제가 해결됩니다. 컬렉션과 기본 클래스에 관해서는 전적으로 명확하지 않았습니다. 메서드와 속성이 동일한 ** 이름 **을 가지지 만 매개 변수와 속성의 데이터 유형은 다릅니다 (예 : 텍스트 상자의 문자열, 숫자의 소수점 등). 따라서 기본 클래스를 구현하고 강력한 타이핑을 유지하는 방법을 알지 못합니다. 내가 떨어지는 것이 꺼려집니다. 여기 내 생각이 결함이있는 것 같습니다 ... –

+0

@BenW. 리플렉션과 결합 된 기본 클래스를 사용하는 방법에 대한 정보를 추가했습니다. –

0

MySettings의 하위 개체의 모든 예를 들어 GroupRefAttr과 같은 클래스에는 동일한 메소드와 속성이 있지만 내부 코드가 다릅니다.

그런 경우 하위 개체 형식은 이러한 동일한 메서드와 속성이 필요하다는 공통 인터페이스를 구현하도록 정의해야합니다. 지금은 해당 인터페이스의 이름을 IControlSetting으로 지정하겠습니다.

Dim Opts as New MySettings 
For Each var In Opts.GetType.GetFields 
    Dim setting As IControlSetting = TryCast(var.GetValue(Opts), IControlSetting) 
    If setting Is Nothing Then Continue 
    setting.RestoreDefault() 
Next 

또한, 나는 사전 또는 IControlSetting 객체를 캡슐화하기 위해 MySettings 유형을 변경 것 : 그런 다음, For 루프는 다음과 같다. 그런 다음 리플렉션이 필요하지 않고 사전을 반복하여 각 객체를 검사 할 수 있습니다. 그러면 다음과 같이 보일 수 있습니다.