type.FindMembers缺少具有绑定标志

时间:2015-12-04 19:48:50

标签: c# .net

编辑:我的单元测试中有错误。所以我的问题无效。我在下面标记了正确的答案,问题应该是"如何让私人成员参与继承的课程"。

我遍历类层次结构以获取我需要的私有成员。

我使用反射来获取类层次结构的成员。最初,我分别拉动了属性和字段。我重构了我的代码只是为了获得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; } }
        }

ViewModelViewModel2

将返回4个字段

然后我改变了要使用的代码(而不是获取属性然后是字段):

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)。使用具有相同绑定标志的GetFieldsGetProperties获取它们时不是这种情况。

如果我将field2更改为受保护,则会显示在搜索中。

这是框架的问题还是我错过了什么?

1 个答案:

答案 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

另外,我必须说我得到FindMembersGetPropertiesGetFields / hp

的相同结果