Bypassing Polymorphism with Reflection

Bypassing Polymorphism with Reflection

Tags
.NET
Code
Published
July 13, 2020
Author
Matthias Koch
While implementing support for interface default implementations in NUKE we’ve added the new fluent methods Base and Inherit. In order to let an overridden target inherit from its base declaration (or a re-implemented target with default implementation), we needed to make non-virtual calls using reflection. This wasn’t exactly easy, since even when reflecting on a member through its declaring type, it will follow the principle of polymorphism and call the member virtual.
With a bit of Stack Overflow, we ended up implementing the following generic method:
public static TResult GetValueNonVirtual<TResult>(this MemberInfo member, object obj, params object[] arguments) { ControlFlow.Assert(member is PropertyInfo || member is MethodInfo, "member is PropertyInfo || member is MethodInfo"); var method = member is PropertyInfo property ? property.GetMethod : (MethodInfo) member; var funcType = Expression.GetFuncType(method.GetParameters().Select(x => x.ParameterType) .Concat(method.ReturnType).ToArray()); var functionPointer = method.NotNull("method != null").MethodHandle.GetFunctionPointer(); var nonVirtualDelegate = (Delegate) Activator.CreateInstance(funcType, obj, functionPointer) .NotNull("nonVirtualDelegate != null"); return (TResult) nonVirtualDelegate.DynamicInvoke(arguments); }
Using the GetValueNonVirtual method, we can use any property or method reflected from a base type, and bypass their overrides:
var method = typeof(object).GetMethod("ToString").Single(); var value = method.GetValueNonVirtual(dto);
I’ll admit it, I’m a reflection addict.