The other day I was doing some work in which I needed to be able to determine from a base class whether a particular method had been overridden in a derived class, and once again reflection comes to the rescue.
Consider the class declarations below;
internal class BaseA { public virtual string GetMappingsForCreate() { return "A"; } public bool TestIfMethodOverridden(string methodName) { var t = this.GetType(); var mi = t.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public); if (mi == null) return false; var declaringType = mi.DeclaringType.FullName; return declaringType.Equals(t.FullName, StringComparison.OrdinalIgnoreCase); } } internal class BaseB : BaseA { public override string GetMappingsForCreate() { return "B"; } } internal class BaseC : BaseA {}
We have some simple inheritance here, a base class BaseA and two deriving classes BaseB and BaseC – only BaseB overrides the single virtual method GetMappingsForCreate(). In base class BaseA there is a method to determine if a given method has been overridden in the class definition of the class instance referred to by this.
Note that it isn’t enough to get the MethodInfo for the method in question, since it will always exist. The key thing here is to evaluate which type declares the method in question – if a derived class doesn’t override a virtual method, the declaring type of the method will be next class down the chain of inhertitance which does override the method, right back down to the base class.
Running the test sample demonstrates this;
var a = new BaseA(); var b = new BaseB(); var c = new BaseC(); Console.WriteLine("BaseA::GetMappingsForCreate = " + a.TestIfMethodOverridden("GetMappingsForCreate")); Console.WriteLine("BaseB::GetMappingsForCreate = " + b.TestIfMethodOverridden("GetMappingsForCreate")); Console.WriteLine("BaseC::GetMappingsForCreate = " + c.TestIfMethodOverridden("GetMappingsForCreate")); Console.WriteLine(); Console.WriteLine("BaseA::GetMappingsForCreate returned " + a.GetMappingsForCreate()); Console.WriteLine("BaseB::GetMappingsForCreate returned " + b.GetMappingsForCreate()); Console.WriteLine("BaseC::GetMappingsForCreate returned " + c.GetMappingsForCreate());
good article!
The following will work without needing string comparisons:
1. Add BindingFlags.DeclaredOnly to your flags.
2. Just do: return mi != null
Also, delegates are a far quicker way of getting the MethodInfo of a known method:
private delegate string GetMappingsForCreateDelegate();
public bool OverridesGetMappingsForCreate()
{
GetMappingsForCreateDelegate del = this.GetMappingsForCreate;
return (del.Method != null && del.Method.DeclaringType == typeof(BaseA));
}
nice one, thanks
Nice post and discussion 🙂 I think that someone looking for this might find this StackOverflow post useful too: “How to determine if the MethodInfo is an override of the base method” – http://stackoverflow.com/questions/982347/how-to-determine-if-the-methodinfo-is-an-override-of-the-base-method