我遍历类层次结构以获取我需要的私有成员。
我使用反射来获取类层次结构的成员。最初,我分别拉动了属性和字段。我重构了我的代码只是为了获得MemberInfo
并开始遇到一个小问题。
最初我能够使用以下所有字段:
type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic)
这将返回类层次结构中的所有公共和私有字段。 例如关于类:
class ViewModel {
[MetaData("MetaFieldType1", typeof(Parent), null)]
public string field1;
[MetaData("MetaFieldType2", typeof(Parent), "Field Value 2")]
private string field2;
[MetaData("MetaProtectedField", typeof(Parent), "Protected Field")]
protected string pField;
protected string pField2;
[MetaData("MetaType 1", typeof(Parent), null)]
public String Prop1 { get; set; }
[MetaData("MetaType 2", typeof(Parent), "The Value")]
public String Prop2 { get; set; }
public string Field2 { get { return field2; } set { field2 = value; } }
}
class ViewModel2 : ViewModel {
public string PField { get { return pField; } set { pField = value; } }
[MetaData("MetaProtectedField2", typeof(Parent), null)]
public string PField2 { get { return pField2; } set { pField2 = value; } }
}
ViewModel
和ViewModel2
然后我改变了要使用的代码(而不是获取属性然后是字段):
type.FindMembers(MemberTypes.Field | MemberTypes.Property,
BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic,
allMemberFilter,null)
哪里
protected static readonly MemberFilter allMemberFilter = new MemberFilter(
delegate (MemberInfo objMemberInfo, Object objSearch) {
return true;
});
和ViewModel
返回所有属性和字段;但是,ViewModel2
缺少field2
中的私人字段(即ViewModel
)。使用具有相同绑定标志的GetFields
和GetProperties
获取它们时不是这种情况。
如果我将field2
更改为受保护,则会显示在搜索中。
这是框架的问题还是我错过了什么?
答案 0 :(得分:0)
首先,基础Type
的私有成员被视为继承Type
的成员。来自 C#语言规范版本5.0 :
一个类继承其基类的成员。继承意味着隐式 的类包含其基类的所有成员 (Aka:包括基类的私有成员),除了实例和静态构造函数,以及基类的析构函数。
如果您查看BindingFlags.FlattenHierarchy
文档,则会看到它仅指static
个成员:
指定应返回层次结构中的公共和受保护静态成员。
有了这样说,显然,不幸的是,获得private
Type
Type
成员的唯一方法是使用反映声明Type
,这意味着,在我们的情况下 - 基数static class TypeExtensions
{
public static IEnumerable<MemberInfo> GetAllInstanceMembers(this Type type)
{
if (type == null || type == typeof (object) || !type.IsClass || type.IsInterface)
{
return Enumerable.Empty<MemberInfo>();
}
IEnumerable<MemberInfo> baseMembers = type.BaseType.GetAllInstanceMembers();
IEnumerable<MemberInfo> interfacesMembers = type.GetInterfaces().SelectMany(x => x.GetAllInstanceMembers());
IEnumerable<MemberInfo> currentMembers = type.FindMembers(MemberTypes.Field | MemberTypes.Property,
BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic,
AllMemberFilter, null);
return baseMembers.Concat(interfacesMembers).Concat(currentMembers);
}
static readonly MemberFilter AllMemberFilter = (objMemberInfo, objSearch) => true;
}
本身。
因此我们必须编写一个扩展来递归地执行此操作:
BindingFlags.DeclaredOnly
请注意,在问题的示例中,显然return
使方法返回自动属性的构造函数生成的支持字段它们不会被退回,可以通过将return baseMembers.Concat(interfacesMembers).Concat(currentMembers)
.Where(x => x.GetCustomAttribute<CompilerGeneratedAttribute>() == null);
行更改为:
GetMembers
另外,我必须说我得到FindMembers
,GetProperties
和GetFields
/ hp