使用方法的MethodHandle作为键来缓存无参数方法的结果是否安全?

Kir*_*rst 5 .net c# reflection caching methodinfo

在WCF客户端应用程序中,有许多无参数方法,我们希望将结果缓存 - GetAllFoo(), GetAllBar(). 这些用于填充下拉列表等,结果在客户端的运行期间不会改变.

这些结果当前由存储在资源文件中的唯一字符串缓存 - 例如,GetAllCountries()缓存在CountryKey资源上.仅当缓存不包含请求的密钥时才会调用该服务.

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;
}
Run Code Online (Sandbox Code Playgroud)

这很好,除了我们需要维护资源文件中的密钥,并且需要确保每个方法都使用正确的缓存密钥,否则会中断.旧的Control + C,Control + V在这里引起一些麻烦,我不想去检查每个调用此方法的地方.

所以问题是:

serviceCall委托具有Method它属性描述要执行的方法.这是一个MethodInfo实例,它又包含一个MethodHandle属性.我是否正确地假设该MethodHandle属性唯一且一致地标识引用的方法?

我将包装器更改为

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

它正确地封装了缓存和关键问题,并消除了对调用者"做正确的事情"的任何依赖.

  • 不关心MethodHandle是否在实例之间发生变化 - 缓存仅适用于每个实例
  • 不关心MethodHandle是否在客户端之间不一致 - 每个客户端都有缓存
  • DO护理如果MethodHandle不是客户端上的实例中一致的-其实我是想使用高速缓存,而不是每个请求产生新的服务调用和缓存已满未使用的数据的
  • 注意MethodHandle在客户端的实例中是不唯一的 - 我必须确保在使用包装器时返回正确的数据(和类型).

Jos*_* M. 2

MSDN 在提到 MethodHandle 属性时说:“此属性用于从非托管代码访问托管类,不应从托管代码调用。”

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

建议:

  • 无论如何,请使用 serviceCall.Method.MethodHandle,因为它在同一 AppDomain 中应该是唯一的。
  • 研究 serviceCall.Method.GetHashCode() 以查看这是否适合您作为缓存密钥。
  • 将缓存机制更改为字典,T> 并使用 serviceCall 作为实际的缓存键。(这可能不起作用,具体取决于您的代码如何调用包装器方法。)