5

在 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;
}

这很好,除了我们需要维护资源文件中的键,并且需要确保每个方法都使用正确的缓存键,否则事情会中断。旧的 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

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

  • 不在乎 MethodHandle 是否在实例之间发生变化 - 缓存仅针对每个实例
  • 不要关心 MethodHandle 是否在客户端之间不一致 - 缓存是每个客户端的
  • 注意 MethodHandle 在客户端实例中是否不一致 - 我实际上希望使用缓存,而不是每个请求都会导致新的服务调用并且缓存中充满未使用的数据
  • 注意 MethodHandle 在客户端实例中是否不是唯一的 - 我必须确保在使用包装器时返回正确的数据(和类型)。
4

1 回答 1

2

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

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

建议:

  • 无论如何都要使用 serviceCall.Method.MethodHandle,因为它应该在同一个 AppDomain 中是唯一的。
  • 研究 serviceCall.Method.GetHashCode() 看看这是否适合你作为你的缓存键。
  • 将您的缓存机制更改为 Dictionary, T> 并使用 serviceCall 作为实际的缓存键。(这可能不起作用,具体取决于您的代码如何调用包装器方法。)
于 2011-03-07T01:25:29.887 回答