Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe to cache the results of a parameterless method using the method's MethodHandle as a key?

In a WCF client application, there are a number of parameterless methods for which we'd like to cache the results - GetAllFoo() , GetAllBar(). These are used to populate dropdowns and the like, and the results don't change during the running life of the client.

These results are currently being cached by a unique string stored in a Resource file - for example, GetAllCountries() is cached against the CountryKey Resource. The service is only called when the cache doesn't contain the requested key.

public T Get<T, V>(string key, Func<V, T> serviceCall, V proxy)
{
    if (!cache.Contains(key))
    {
        cache.Add(key, serviceCall(proxy));
    }   
    return cache.GetData(key) as T;
}

This is fine except we need to maintain the keys in the Resource file, and need to make sure that every method uses the correct cache key otherwise things break. The old Control+C, Control+V causes a few headaches here and I don't want to have to go check every place that calls this method.

So the question:

The serviceCall delegate has a Method property on it which describes the method to execute. This is a MethodInfo instance, which in turn contains a MethodHandle property. Am I right in assuming that the MethodHandle property uniquely and consistently identifies the method that is referenced?

I'd change the wrapper to

public T Get<T, V>(Func<V, T> serviceCall, V proxy)
{
    var key = serviceCall.Method.MethodHandle;
    // etc

which properly encapsulates the caching and key concerns, & removes any dependency on the caller 'doing the right thing'.

  • Don't care if the MethodHandle changes between instances - the caching is only per instance
  • Don't care if the MethodHandle is not consistent across clients - caching is per client
  • DO care if the MethodHandle is not consistent within an instance on a client - I actually want the cache to be used, rather than every request resulting in a new service call and the cache being full of unused data
  • DO care if the MethodHandle is not unique within an instance on a client - I have to be sure that the correct data (and type) is returned when the wrapper is used.
like image 839
Kirk Broadhurst Avatar asked Nov 05 '22 01:11

Kirk Broadhurst


1 Answers

MSDN, referring to the MethodHandle property, says "this property is for access to managed classes from unmanaged code and should not be called from managed code."

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices._methodbase.methodhandle.aspx

Suggestions:

  • Use serviceCall.Method.MethodHandle anyway since it is supposed to be unique within the same AppDomain.
  • Research serviceCall.Method.GetHashCode() to see if this would work for you as your caching key.
  • Change your caching mechanism to be a Dictionary, T> and use serviceCall as the actual caching key. (This may not work depending on how you're code is calling the wrapper method.)
like image 129
Josh M. Avatar answered Nov 09 '22 11:11

Josh M.