gettype ()에서 필드를 얻지 못함 bindingflag.default가있는 getfields
-
18-09-2019 - |
문제
모든 필드를 특정 객체 내부에 가져 오기 위해 반사 클래스를 사용하고 있습니다. 그러나 내 문제는 필드가 일반 클래스 내에있을 때 완벽하게 작동한다는 것입니다.
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);