当一个属性隐藏了一个带有“new”关键字的继承成员时,反射如何告诉我?如果我有:publicclassChildClass:BaseClass{publicnewvirtualstringTempProperty{get;放;}}publicclassBaseClass{publicvirtualstringTempProperty{get;?我想在c#和vb.net之间做出一个不可知论的答案我们必须在这里处理属性的方法而不是属性本身,因为它是属性的get/set方法,它实际上被覆盖而不是属性本身。我将使用get方法,因为您永远不应该拥有属性,尽管完整的解决方案应该检查是否缺少属性。查看在许多情况下发出的IL,基本属性的“get”方法将具有元数据标记(这来自C#编译器;其他方法可能不会发出hidebysig,具体取决于它们隐藏的语义,在这种情况下,方法将是隐藏名称):非虚拟:.methodpublichidebysigspecialnameinstancevirtual:.methodpublichidebysigspecialnamenewslotvirtualinstancederived将具有以下标记:override:.methodpublichidebysigspecialnamevirtualinstancenew:.methodpublichidebysiginstancenewvirtual:.methodpublichidebysigspecialnamenewslotvirtualinstance所以从这里我们可以看出,由于非虚基方法和非虚new方法有相同的tag,而虚基方法也有相同的tag,所以不可能完全从方法的Metadata标签中读取判断是否是新的。与新虚拟方法相同的标记。我们可以说的是,如果一个方法有一个虚拟标记而不是新槽标记,那么它会覆盖基方法而不是隐藏它,即varprop=typeof(ChildClass).GetProperty("TempProperty");vargetMethod=道具。获取获取方法();if((getMethod.Attributes&MethodAttributes.Virtual)!=0&&(getMethod.Attributes&MethodAttributes.NewSlot)==0){//属性的'get'方法是重写}所以,假设我们找到'get'方法不是覆盖,我们想知道基类中是否有属性被隐藏。问题是因为该方法位于不同的方法表槽中,所以它实际上与它隐藏的方法没有任何直接关系。所以我们实际上要说的是“基类型是否有任何影子兼容方法”,这取决于方法是hidebysig还是hide-by-name。对于前者我们需要检查基类是否有与签名完全匹配的方法,对于后者我们需要检查它是否有同名方法,所以继续上面的代码:else{if(getMethod.IsHideBySig){varflags=getMethod.IsPublic?BindingFlags.Public:BindingFlags.NonPublic;标志|=getMethod.IsStatic?BindingFlags.Static:BindingFlags.实例;varparamTypes=getMethod.GetParameters().Select(p=>p.ParameterType)。ToArray();if(getMethod.DeclaringType.BaseType.GetMethod(getMethod.Name,flags,null,paramTypes,null)!=null){//属性的“get”方法通过签名隐藏}}else{varflags=BindingFlags.Public|绑定标志.NonPublic|BindingFlags.静态|BindingFlags.Instance;if(getMethod.DeclaringType.BaseType.GetMethods(flags).Any(m=>m.Name==getMethod.Name)){//属性的“get”方法按名称隐藏}}}我认为这是大部分方式,但我仍然不认为这是完全正确的。首先,我并不完全熟悉隐藏名称,因为C#不支持它,而这正是我正在使用的,所以我在此处的代码中可能是错误的,这表明实例方法可以影响静态方法。我也不知道区分大小写的问题(例如,在VB中,你可以有一个名为Fooshadow的方法,如果它们具有相同的签名并且都是hidebysig,则称为foo,在C#中答案是否定的,但如果答案是,那么VB则表示这道题的答案其实是不确定的)。好吧,我不确定所有这些都有多大帮助,除了说明它实际上比我想象的要困难得多(或者我遗漏了一些非常明显的东西,在这种情况下我想知道!)。但希望它能提供足够的信息,帮助您实现您想要做的事情。看起来反射不会默认给你这个,所以你必须自己做:publicstaticboolIsHidingMember(thisPropertyInfoself){PropertyInfobaseProperty=baseType.GetProperty(self.Name,self.PropertyType);如果(baseProperty==null){返回false;}如果(baseProperty.DeclaringType==self.DeclaringType){返回假;}varbaseMethodDefinition=baseProperty.GetGetMethod().GetBaseDefinition();varthisMethodDefinition=self.GetGetMethod().GetBaseDefinition();返回baseMethodDefinition.DeclaringType!=thisMethodDefinition.DeclaringType;但是,不知道这对索引属性有何作用!我从来没有做过你想做的事,但MethodInfo.GetBaseDefinition()方法似乎是你正在寻找的。它返回此方法覆盖的MethodInfo。来自MSDN:如果给定的方法是用new关键字指定的(如TypeMembers中描述的新闻槽),则返回给定的方法。更正,如果您使用的是VB,则您要查找的属性是“IsHideBySig”。在使用“new”关键字定义方法/属性的情况下,这将是一个错误。在C#的情况下,两个实例都输出为“hidebysig”。感谢格雷格指出这一点。我没有意识到我只在VB中测试过这个。下面是将重现此行为的示例VB代码。以上是C#学习教程:当一个属性隐藏了一个带有'new'关键字的继承成员时,反射如何告诉我?分享的所有内容,如果对你有用,需要了解更多C#学习教程,希望大家多多关注—ModuleModule1ClassFooPublicFunctionSomeFunc()AsIntegerReturn42EndFunctionEndClassClassBarInheritsFooPublicShadowsFunctionSomeFunc()AsIntegerReturn36EndFunctionEndClassSubMain()Dimtype=GetType(Bar)Dimfunc=type.GetMethod("SomeFunc")StopEndSubEndModule本文收集自网络,不代表立场,如侵权请点击右侧联系管理员删除。如需转载请注明出处:
