Performance Guideline: Use Token Handle Resolution API to get the Metadata for Reflection

Here's the next .NET Framework 2.0 performance guideline in the series from Prashant Bansode, Bhavin Raichura, Girisha Gadikere and Claudio Caldato.

 ...

Use Token Handle Resolution API to get the Metadata for Reflection

Applies to

  • .NET 2.0

What to Do
Use the new .NET 2.0 token handle resolution API RuntimeMethodHandle to get the Metadata of members while using Reflection.

Why
The RuntimeMethodHandle is a small, lightweight structure that defines the identity of a member. RuntimeMethodHandle is a trimmed down version of MemberInfos, which provides the metadata for the methods and data without consuming .NET 2.0 back-end cache.

The .NET Framework also provides GetXxx type of API methods for e.g.. GetMethod, GetProperty, GetEvent to determine the metadata of given Type at runtime. There are two forms of these APIs, the non-plural, which return one MemberInfo (such as GetMethod), and the plural APIs (such as GetMethods).

The .NET framework implements a back-end cache for the MemberInfo metadata to improve the performance of GetXxx API.

The caching policy is implemented irrespective of plural or non-plural GetXxx API call. Such eager caching policy degrades the performance on calls to or non-plural GetXxx API calls.

RuntimeMethodHandle works approximately twice faster than compared to equivalent GetXxx API call, if the MemberInfo is not present in the back-end .NET cache.

When
If it is required to get the metadata of a given Type at runtime, use new .NET 2.0 token handle resolution API RuntimeMethodHandle for better performance than traditional GetXxx API calls.

How
The following code snippet shows how to get the RuntimeMethodHandle:

 ...
    // Obtaining a Handle from an MemberInfo
    RuntimeMethodHandle handle = typeof(D).GetMethod("MyMethod").MethodHandle;
 ...

The following code snippet shows how to get the MemeberInfo metadata from the handle:

 ...
    // Resolving the Handle back to the MemberInfo
    MethodBase mb = MethodInfo.GetMethodFromHandle(handle);
 ...

Problem Example
A Windows Forms based application needs to dynamically load the plug-in Assemblies and available Types. The application also needs to determine the metadata of a given Type (methods, members etc) at runtime to execute Reflection calls.

The plug-in exposes a Type CustomToolBar, which is derived from Type BaseToolBar. The CustomToolBar Type has 2 methods - PrepareCommand, ExecuteCommand. The BaseToolBar Type has 3 methods - Initialize, ExecuteCommand and CleanUp. To execute the ExecuteCommand method of type CustomToolBar at runtime, it gets the metadata of that method using GetXxx API as shown in the following code snippet.

Since the .NET Framework implements eager caching policy, the call to get the metadata for a single ExecuteCommand method will also get the metadata of all the five methods of CustomToolBar and BaseToolBarTypes.

    MethodInfo mi = typeof(CustomToolBar).GetMethod("ExecuteCommand");

The .NET framework implements a back-end cache for the MemberInfo metadata to improve the performance of GetXxx API. The implemented caching policy caches all members by default, irrespective of plural or non-plural API call. Such eager caching policy degrades the performance on calls to or non-plural GetXxx API calls.

Solution Example
A Windows Forms based application needs to dynamically load the plug-in Assemblies and available Types. The application also needs to determine the metadata of a given Type (methods, members etc) at runtime to execute Reflection calls.

The plug-in exposes a Type CustomToolBar, which is derived from Type BaseToolBar. The CustomToolBar Type has 2 methods - PrepareCommand, ExecuteCommand. The BaseToolBar Type has 3 methods - Initialize, ExecuteCommand and CleanUp. To execute the ExecuteCommand method of type CustomToolBar at runtime, it gets the metadata of that method using RuntimeMethodHandle is used, as shown in the following code snippet. This can improve the performance of the application. :

 ...
    // Obtaining a Handle from an MemberInfo
    RuntimeMethodHandle handle = typeof(CustomToolBar).GetMethod("ExecuteComand").MethodHandle;
    // Resolving the Handle back to the MemberInfo
    MethodBase mb = MethodInfo.GetMethodFromHandle(handle);
 ...

If the appropriate MemberInfo is already in the back-end .NET cache, the cost of going from a handle to a MemberInfo is about the same as using one of the GetXxx API call. If the MemberInfo is not available in the cache RuntimeMethodHandle is approximately twice faster than the GetXxx API call.

Additional Resources