문제

모든 필드를 특정 객체 내부에 가져 오기 위해 반사 클래스를 사용하고 있습니다. 그러나 내 문제는 필드가 일반 클래스 내에있을 때 완벽하게 작동한다는 것입니다.

class test
{
   string test1 = string.Empty;
   string test2 = string.Empty;
}

여기서 나는 test1과 test2를 모두 얻습니다. 내 문제는 추상화를 사용하여 여러 클래스를 결합한다는 것입니다.

나는 다음과 같은 것을 얻었다.

class test3 : test2
{
   string test4 = string.Empty;
   string test5 = string.Empty;
}

class test2 : test1
{
   string test2 = string.Empty;
   string test3 = string.Empty;
}
class test1
{
   string test0 = string.Empty;
   string test1 = string.Empty;
}

그러나 내가 그것을 실행할 때, 나는 필드를 다시 얻지 못합니다. GetType().GetFields(BindingFlag.Default).

해당 분야의 모든 사람들도 속성이 있으며 get; set; 그것에 첨부. 코드를 실행할 때 속성을 Test1로 되돌릴 수는 있지만 실제 필드는 아닙니다.

이것은 필드를 가져 오려고하는 코드입니다.

FieldInfo[] fields = Obj.GetType().GetFields(BindingFlags.Default);
foreach (FieldInfo field in fields)

나는 또한 시도했다 :

FieldInfo[] fields = Obj.GetType().GetFields(BindingFlags.Public 
                                             | BindingFlags.Instance 
                                             | BindingFlags.NonPublic 
                                             | BindingFlags.Static);

속성에 대해 동일한 코드를 사용합니다.

PropertyInfo[] properties = Obj.GetType().GetProperties(BindingFlags.Public 
                                             | BindingFlags.Instance 
                                             | BindingFlags.NonPublic 
                                             | BindingFlags.Static);

foreach (PropertyInfo property in properties)

내가 추상 클래스에서 속성을 얻지 만 필드가 아닌 이유는 무엇입니까?

도움이 되었습니까?

해결책

편집 : 얻으려면 사적인 기본 유형의 구성원은 다음을해야합니다.

typeof(T).BaseType.GetFields(...)

다시 편집 : 승리.

3/22/13 편집 : 사용 Concat 대신에 Union. 우리가 지정하기 때문에 BindingFlags.DeclaredOnly 그리고 유형 BaseType 스스로 동일 할 수없고 Union 필요하지 않으며 더 비싸다.

public static IEnumerable<FieldInfo> GetAllFields(Type t)
{
    if (t == null)
        return Enumerable.Empty<FieldInfo>();

    BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | 
                         BindingFlags.Static | BindingFlags.Instance | 
                         BindingFlags.DeclaredOnly;
    return t.GetFields(flags).Concat(GetAllFields(t.BaseType));
}

다른 팁

다른 유형을 상속하는 유형은 다른 유형의 개인 부분을 볼 수 없으며 보호 된 내부 및 공공 부품을 볼 수 있습니다. 다음 코드를 고려하십시오.

class A
{
    // note that this field is private
    string PrivateString = string.Empty;
    // protected field
    protected string ProtectedString = string.Empty;
}

class B : A { }

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("B Fields:");
        B b = new B();
        b.GetType()
            .GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
            .ToList()
            .ForEach(f => Console.WriteLine(f.Name));

        Console.WriteLine("A Fields:");
        A a = new A();
        a.GetType()
            .GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
            .ToList()
            .ForEach(f => Console.WriteLine(f.Name));

    }
}

이 프로그램의 출력은 다음과 같습니다.

B Fields:
ProtectedString
A Fields:
PrivateString
ProtectedString

그래서, 유형 A 두 개의 필드가 있습니다. PrivateString 그리고 ProtectedString. 유형 B 하나가있다; ProtectedString, 그것은 상속합니다 A. "도달"하고 싶다면 PrivateString 유형을 통해 B, 기본 유형으로 이동해야합니다 (b.GetType().BaseType).

그러나 유형이라도 마찬가지입니다 B 필드를 호출하는 보고서 ProtectedString,이 필드는 여전히 선언되지 않았습니다 B; 그것은 선언됩니다 A. 이것은 추가하여 검사 할 수 있습니다 BindingFlags.DeclaredOnly ~로 GetFields 위의 샘플 프로그램에서 호출; GetFields 필드를 반환하지 않습니다 B, 그리고 두 가지 A.

코드 샘플로 변환 된 경우 test3 필드가 포함되어 있지 않습니다 test2 그리고 test3, 그들은 유형에 비공개이기 때문에 test2 (필드 이름과 유형 이름의 유사성은 그 문장을 다소 혼란스럽게 만듭니다.

이 확장 방법을 사용하여 유형의 상속 계층 구조를 객체까지 재귀 적으로 통과하여 유형의 모든 필드와 모든 조상을 효과적으로 반환 할 수 있습니다.

public static class ReflectionExtensions
{
    public static IList<FieldInfo> GetAllFields(this Type type, BindingFlags flags)
    {
        if(type == typeof(Object)) return new List<FieldInfo>();

        var list = type.BaseType.GetAllFields(flags);
        // in order to avoid duplicates, force BindingFlags.DeclaredOnly
        list.AddRange(type.GetFields(flags | BindingFlags.DeclaredOnly));
        return list;
    }
}

(테스트되지 않은, ymmv)

속성은 상속되며 필드는 그렇지 않습니다. 보호 된 필드는 자손 클래스로 보이지만 그에 의해 상속되지는 않습니다. 다시 말해, 자손 클래스는 실제로 기본 클래스의 속성을 가지고 있지만 필드를 볼 수 있습니다.

속성과 필드의 이름을 원한다면 사용하십시오.

private static IEnumerable<string > GetAllFieldsAndProperties(Type t)
{
  if (t == null)
    return Enumerable.Empty<string>();

  BindingFlags flags = BindingFlags.Public 
    | BindingFlags.NonPublic 
    | BindingFlags.Static 
    | BindingFlags.Instance 
    | BindingFlags.DeclaredOnly;
  return t.GetFields(flags).Select(x=>x.Name)
    .Union(GetAllFieldsAndProperties(t.BaseType))
    .Union(t.GetProperties(flags).Select(x=>x.Name));
}

기본 클래스의 개인 구성원을 포함한 모든 유형 필드의 열거.

public static IEnumerable<FieldInfo> EnumerateFields(this Type type, BindingFlags flags) =>
   type.BaseType?.EnumerateFields(flags)
       .Concat(type.GetFields(flags | BindingFlags.DeclaredOnly)) ??
   type.EnumerateFields(flags);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top