GDPR Cookie Consent by Free Privacy Policy Bypassing Polymorphism with Reflection in .NET - Matthias Koch

Bypassing Polymorphism with Reflection in .NET

 

Photo by JJ Shev on Unsplash

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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:

1
2
var method = typeof(object).GetMethod("ToString").Single();
var value = method.GetValueNonVirtual(dto);

Reflection FTW! 😎