Безопасно ли кэшировать результаты метода без параметров, используя метод MethodHandle в качестве ключа? - PullRequest
5 голосов
/ 04 марта 2011

В клиентском приложении 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;
}

Это нормально, за исключением того, что нам нужно поддерживать ключи в файле Resource, и нужно убедиться, что каждый метод использует правильный ключ кеша, в противном случае что-то сломается. Старый 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 не был уникальным в экземпляре на клиенте - я должен быть уверен, что при использовании оболочки возвращается правильные данные (и тип).

1 Ответ

2 голосов
/ 07 марта 2011

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 в качестве фактического ключа кеширования.(Это может не работать в зависимости от того, как ваш код вызывает метод-обертку.)
...