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.