How is a story reflected when a property hides an inherited member with a “new” keyword?

So, if I have:

public class ChildClass : BaseClass { public new virtual string TempProperty { get; set; } } public class BaseClass { public virtual string TempProperty { get; set; } } 

How can I use reflection to see ChildClass hiding the underlying TempProperty implementation?

I would like the answer to be agnostic between C # and vb.net

+18
override inheritance reflection c #
Nov 13 '08 at 21:18
source share
4 answers

We will have to deal with the methods here, and not with the property itself, because these are get / set methods of the property that are actually overridden, and not the properties themselves. I will use the get method since you will never have a property without it, although the complete solution should check for its absence.

Looking at IL, emitted in some cases, the get get method of the base property will have metadata tokens (this is from the C # compiler, others may not allocate hidebysig depending on their method that hides semantics, in which case the method will hide by name):

 non-virtual : .method public hidebysig specialname instance virtual : .method public hidebysig specialname newslot virtual instance 

The resulting code will have the following tokens:

 override : .method public hidebysig specialname virtual instance new : .method public hidebysig specialname instance new virtual : .method public hidebysig specialname newslot virtual instance 

Thus, it can be seen from the method’s metadata tokens that it is impossible to determine whether it is new , because the non-virtual base method has the same tokens as the non-virtual new method and the virtual base method has the same tokens as the new virtual method new virtual .

We can say that if a method has a virtual token, but not a newslot token, then it overrides the base method, not its shadows, i.e.

 var prop = typeof(ChildClass).GetProperty("TempProperty"); var getMethod = prop.GetGetMethod(); if ((getMethod.Attributes & MethodAttributes.Virtual) != 0 && (getMethod.Attributes & MethodAttributes.NewSlot) == 0) { // the property 'get' method is an override } 

Assuming we find that the get method is not an override, we want to know if there is a property in the base class that it obscures. The problem is that, since the method is in another slot in the method table, it actually has no direct relation to the method that it hides. So we’re actually saying, “The base type has some method that meets the criteria for shading,” which depends on whether the hidebysig method or the hidden name.

For the first, we need to check whether the base class has any method that exactly matches the signature, while for the last we need to check whether it has any method with the same name, therefore continuing the code above:

 else { if (getMethod.IsHideBySig) { var flags = getMethod.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic; flags |= getMethod.IsStatic ? BindingFlags.Static : BindingFlags.Instance; var paramTypes = getMethod.GetParameters().Select(p => p.ParameterType).ToArray(); if (getMethod.DeclaringType.BaseType.GetMethod(getMethod.Name, flags, null, paramTypes, null) != null) { // the property 'get' method shadows by signature } } else { var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance; if (getMethod.DeclaringType.BaseType.GetMethods(flags).Any(m => m.Name == getMethod.Name)) { // the property 'get' method shadows by name } } } 

I think this is a big part of the way, but I still don't think it is right. For starters, I'm not completely familiar with hiding by name, since C # does not support it, and that is almost all that I use, so I may be mistaken in the code here that indicates that the instance method can obscure the static. I also don’t know about the case sensitivity problem (for example, in VB the method called Foo shadow is called the Foo method, if both of them have the same signature and both were hidebysig in C #, the answer is no, but if the answer is yes in VB, this means that the answer to this question is actually non-deterministic).

Well, I'm not sure how much this helps, except to illustrate that it is actually much more complicated than I thought it would be (or I missed something really obvious, in which case I would like to know!). But hopefully he has received enough content to help you achieve what you are trying to do.

+21
Nov 14 '08 at 0:57
source share

It does not look like reflection will provide you with a default, so you have to minimize it yourself:

 public static bool IsHidingMember( this PropertyInfo self ) { Type baseType = self.DeclaringType.BaseType; PropertyInfo baseProperty = baseType.GetProperty( self.Name, self.PropertyType ); if ( baseProperty == null ) { return false; } if ( baseProperty.DeclaringType == self.DeclaringType ) { return false; } var baseMethodDefinition = baseProperty.GetGetMethod().GetBaseDefinition(); var thisMethodDefinition = self.GetGetMethod().GetBaseDefinition(); return baseMethodDefinition.DeclaringType != thisMethodDefinition.DeclaringType; } 

Not sure how this will work with indexed properties, however!

+3
Nov 13 '08 at 23:13
source share

I never did what you are trying to do, but the MethodInfo.GetBaseDefinition () method seems to be what you are looking for.

It returns MethodInfo, this method overrides.

From MSDN:

If the specified method is specified with a new keyword (as in the news channel, as described in type members), this method is returned.

0
Nov 13 '08 at 22:32
source share

Correction, if you use VB, you are looking for "IsHideBySig". This will be false if a “new” keyword was used to define a method / property.

In the case of C #, both instances are displayed as "hidebysig". Thanks for pointing to Greg. I did not understand that I tested this only in VB. Here is an example of VB code that will reproduce this behavior.

 Module Module1 Class Foo Public Function SomeFunc() As Integer Return 42 End Function End Class Class Bar Inherits Foo Public Shadows Function SomeFunc() As Integer Return 36 End Function End Class Sub Main() Dim type = GetType(Bar) Dim func = type.GetMethod("SomeFunc") Stop End Sub End Module 
-one
Nov 13 '08 at 21:22
source share



All Articles