Reflection을 사용하여 개인 필드를 찾으시겠습니까?
이 클래스가 주어집니다.
class Foo
{
// Want to find _bar with reflection
[SomeAttribute]
private string _bar;
public string BigBar
{
get { return this._bar; }
}
}
속성으로 표시할 개인 항목 _bar를 찾고 싶습니다.그게 가능한가요?
속성을 검색한 속성으로 이 작업을 수행했지만 개인 구성원 필드는 수행한 적이 없습니다.
개인 필드를 가져오기 위해 설정해야 하는 바인딩 플래그는 무엇입니까?
사용하다BindingFlags.NonPublic
그리고.BindingFlags.Instance
깃발들
FieldInfo[] fields = myType.GetFields(
BindingFlags.NonPublic |
BindingFlags.Instance);
속성을 사용하는 것처럼 이 작업을 수행할 수 있습니다.
FieldInfo fi = typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance);
if (fi.GetCustomAttribute(typeof(SomeAttribute)) != null)
...
리플렉션을 사용하여 전용 변수의 값을 가져옵니다.
var _barVariable = typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(objectForFooClass);
Reflection(반사)을 사용하여 전용 변수의 값을 설정합니다.
typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(objectForFoocClass, "newValue");
여기서 objectForFooClass는 클래스 유형 Foo에 대한 null이 아닌 인스턴스입니다.
확장 메서드가 있는 Nice 구문
다음과 같은 코드를 사용하여 임의 유형의 개인 필드에 액세스할 수 있습니다.
Foo foo = new Foo();
string c = foo.GetFieldValue<string>("_bar");
이를 위해 다음과 같은 작업을 수행할 확장 방법을 정의해야 합니다.
public static class ReflectionExtensions {
public static T GetFieldValue<T>(this object obj, string name) {
// Set the flags so that private and public fields from instances will be found
var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
var field = obj.GetType().GetField(name, bindingFlags);
return (T)field?.GetValue(obj);
}
}
개인 구성원을 반영할 때 한 가지 주의해야 할 점은 응용프로그램이 일반 신뢰 상태에서 실행 중인 경우(예: 공유 호스팅 환경에서 실행 중인 경우)에는 이러한 구성원을 찾을 수 없다는 점입니다.비공용 옵션은 무시됩니다.
typeof(MyType).GetField("fieldName", BindingFlags.NonPublic | BindingFlags.Instance)
다음은 간단한 개인 필드 및 속성 가져오기 및 설정(세터가 있는 속성)에 대한 몇 가지 확장 방법입니다.
사용 예:
public class Foo { private int Bar = 5; } var targetObject = new Foo(); var barValue = targetObject.GetMemberValue("Bar");//Result is 5 targetObject.SetMemberValue("Bar", 10);//Sets Bar to 10
코드:
/// <summary>
/// Extensions methos for using reflection to get / set member values
/// </summary>
public static class ReflectionExtensions
{
/// <summary>
/// Gets the public or private member using reflection.
/// </summary>
/// <param name="obj">The source target.</param>
/// <param name="memberName">Name of the field or property.</param>
/// <returns>the value of member</returns>
public static object GetMemberValue(this object obj, string memberName)
{
var memInf = GetMemberInfo(obj, memberName);
if (memInf == null)
throw new System.Exception("memberName");
if (memInf is System.Reflection.PropertyInfo)
return memInf.As<System.Reflection.PropertyInfo>().GetValue(obj, null);
if (memInf is System.Reflection.FieldInfo)
return memInf.As<System.Reflection.FieldInfo>().GetValue(obj);
throw new System.Exception();
}
/// <summary>
/// Gets the public or private member using reflection.
/// </summary>
/// <param name="obj">The target object.</param>
/// <param name="memberName">Name of the field or property.</param>
/// <returns>Old Value</returns>
public static object SetMemberValue(this object obj, string memberName, object newValue)
{
var memInf = GetMemberInfo(obj, memberName);
if (memInf == null)
throw new System.Exception("memberName");
var oldValue = obj.GetMemberValue(memberName);
if (memInf is System.Reflection.PropertyInfo)
memInf.As<System.Reflection.PropertyInfo>().SetValue(obj, newValue, null);
else if (memInf is System.Reflection.FieldInfo)
memInf.As<System.Reflection.FieldInfo>().SetValue(obj, newValue);
else
throw new System.Exception();
return oldValue;
}
/// <summary>
/// Gets the member info
/// </summary>
/// <param name="obj">source object</param>
/// <param name="memberName">name of member</param>
/// <returns>instanse of MemberInfo corresponsing to member</returns>
private static System.Reflection.MemberInfo GetMemberInfo(object obj, string memberName)
{
var prps = new System.Collections.Generic.List<System.Reflection.PropertyInfo>();
prps.Add(obj.GetType().GetProperty(memberName,
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.FlattenHierarchy));
prps = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Where( prps,i => !ReferenceEquals(i, null)));
if (prps.Count != 0)
return prps[0];
var flds = new System.Collections.Generic.List<System.Reflection.FieldInfo>();
flds.Add(obj.GetType().GetField(memberName,
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.FlattenHierarchy));
//to add more types of properties
flds = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Where(flds, i => !ReferenceEquals(i, null)));
if (flds.Count != 0)
return flds[0];
return null;
}
[System.Diagnostics.DebuggerHidden]
private static T As<T>(this object obj)
{
return (T)obj;
}
}
저는 개인적으로 이 방법을 사용합니다.
if (typeof(Foo).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Any(c => c.GetCustomAttributes(typeof(SomeAttribute), false).Any()))
{
// do stuff
}
예, 그러나 개인 필드를 검색하도록 바인딩 플래그를 설정해야 합니다(클래스 인스턴스 외부에서 구성원을 찾는 경우).
필요한 바인딩 플래그는 시스템입니다.반사.바인딩 플래그입니다.비공용
구글에서 이것을 검색하던 중 우연히 발견하여 오래된 게시물에 부딪히고 있다는 것을 깨달았습니다.그러나 GetCustomAttributes에는 두 개의 매개 변수가 필요합니다.
typeof(Foo).GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Where(x => x.GetCustomAttributes(typeof(SomeAttribute), false).Length > 0);
두 번째 매개 변수는 상속 계층을 검색할지 여부를 지정합니다.
만약에.넷 프레임워크가 4.5보다 큽니다.GetRuntimeFields 메서드를 사용할 수 있습니다.
이 메서드는 상속된 필드, 비공용 필드, 인스턴스 필드 및 정적 필드를 포함하여 지정된 유형에 정의된 모든 필드를 반환합니다.
var foo = new Foo();
var fooFields = foo.GetType().GetRuntimeFields()
언급URL : https://stackoverflow.com/questions/95910/find-a-private-field-with-reflection
'itsource' 카테고리의 다른 글
MongoDB용 GUI 도구 (0) | 2023.05.22 |
---|---|
코드를 사용하여 WPF에서 메뉴 구분 기호 표시줄을 만드는 방법 (0) | 2023.05.22 |
특정 유형(버튼/텍스트 상자)의 Windows Forms 양식에 대한 모든 하위 컨트롤을 가져오는 방법은 무엇입니까? (0) | 2023.05.22 |
Python vs Bash - 성능 측면에서 각 작업이 다른 작업을 능가합니까? (0) | 2023.05.17 |
WPF 데이터 그리드에서 스크롤 막대를 활성화하려면 어떻게 해야 합니까? (0) | 2023.05.17 |