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

发布于 2024-10-19 23:53:41 字数 1317 浏览 2 评论 0原文

在 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 是否在客户端之间不一致 - 缓存针对每个客户端
  • DO 关心 MethodHandle 是否在内部不一致客户端上的一个实例 - 我实际上希望使用缓存,而不是每个请求都导致新的服务调用,并且缓存中充满了未使用的数据
  • DO 关心 MethodHandle 在一个实例中是否不是唯一的客户端上的实例 - 我必须确保使用包装器时返回正确的数据(和类型)。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

情仇皆在手 2024-10-26 23:53:41

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

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

建议:

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

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.)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文