C# 使用 Reflection 查找私有字段?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/95910/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Find a private field with Reflection?
提问by David Basarab
Given this class
鉴于这个类
class Foo
{
// Want to find _bar with reflection
[SomeAttribute]
private string _bar;
public string BigBar
{
get { return this._bar; }
}
}
I want to find the private item _bar that I will mark with a attribute. Is that possible?
我想找到我将用属性标记的私有项 _bar。那可能吗?
I have done this with properties where I have looked for an attribute, but never a private member field.
我已经使用我寻找属性的属性完成了此操作,但从未使用过私有成员字段。
What are the binding flags that I need to set to get the private fields?
我需要设置哪些绑定标志才能获取私有字段?
采纳答案by Bob King
Use BindingFlags.NonPublic
and BindingFlags.Instance
flags
使用BindingFlags.NonPublic
和BindingFlags.Instance
标志
FieldInfo[] fields = myType.GetFields(
BindingFlags.NonPublic |
BindingFlags.Instance);
回答by mmattax
Yes, however you will need to set your Binding flags to search for private fields (if your looking for the member outside of the class instance).
是的,但是您需要设置绑定标志来搜索私有字段(如果您在类实例之外寻找成员)。
The binding flag you will need is: System.Reflection.BindingFlags.NonPublic
您需要的绑定标志是: System.Reflection.BindingFlags.NonPublic
回答by Darren Kopp
typeof(MyType).GetField("fieldName", BindingFlags.NonPublic | BindingFlags.Instance)
回答by Abe Heidebrecht
You can do it just like with a property:
您可以像使用属性一样执行此操作:
FieldInfo fi = typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance);
if (fi.GetCustomAttributes(typeof(SomeAttribute)) != null)
...
回答by jammycakes
One thing that you need to be aware of when reflecting on private members is that if your application is running in medium trust (as, for instance, when you are running on a shared hosting environment), it won't find them -- the BindingFlags.NonPublic option will simply be ignored.
在反映私有成员时,您需要注意的一件事是,如果您的应用程序以中等信任度运行(例如,当您在共享托管环境中运行时),它将找不到它们—— BindingFlags.NonPublic 选项将被忽略。
回答by Gunner
I came across this while searching for this on google so I realise I'm bumping an old post. However the GetCustomAttributes requires two params.
我在谷歌上搜索时遇到了这个,所以我意识到我撞到了一个旧帖子。但是 GetCustomAttributes 需要两个参数。
typeof(Foo).GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Where(x => x.GetCustomAttributes(typeof(SomeAttribute), false).Length > 0);
The second parameter specifies whether or not you wish to search the inheritance hierarchy
第二个参数指定是否要搜索继承层次结构
回答by Suriya
Get private variable's value using Reflection:
使用反射获取私有变量的值:
var _barVariable = typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(objectForFooClass);
Set value for private variable using Reflection:
使用反射设置私有变量的值:
typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(objectForFoocClass, "newValue");
Where objectForFooClass is a non null instance for the class type Foo.
其中 objectForFooClass 是类类型 Foo 的非空实例。
回答by sa_ddam213
I use this method personally
我个人使用这种方法
if (typeof(Foo).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Any(c => c.GetCustomAttributes(typeof(SomeAttribute), false).Any()))
{
// do stuff
}
回答by epsi1on
Here is some extension methods for simple get and set private fields and properties (properties with setter):
以下是一些用于简单获取和设置私有字段和属性(带有 setter 的属性)的扩展方法:
usage example:
用法示例:
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
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
Code:
代码:
/// <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;
}
}
回答by Bruno Zell
Nice Syntax With Extension Method
带有扩展方法的漂亮语法
You can access any private field of an arbitrary type with code like this:
您可以使用如下代码访问任意类型的任何私有字段:
Foo foo = new Foo();
string c = foo.GetFieldValue<string>("_bar");
For that you need to define an extension method that will do the work for you:
为此,您需要定义一个扩展方法来为您完成工作:
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);
}
}