2011-03-04 10 views
5

En una aplicación cliente WCF, hay una serie de métodos sin parámetros para los que nos gustaría almacenar en caché los resultados: GetAllFoo(), GetAllBar(). Estos se utilizan para rellenar menús desplegables y similares, y los resultados no cambian durante la vida útil del cliente.¿Es seguro almacenar en caché los resultados de un método sin parámetros utilizando MethodHandle del método como clave?

Actualmente, estos resultados se almacenan en caché mediante una cadena única almacenada en un archivo de recursos; por ejemplo, GetAllCountries() se almacena en caché en el recurso CountryKey. El servicio solo se llama cuando la memoria caché no contiene la clave solicitada.

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

Esto está bien, excepto que necesitamos para mantener las claves en el archivo de recursos, y la necesidad de asegurarse de que cada método utiliza la clave de caché correcto de lo contrario las cosas se rompen. El antiguo Control + C, Control + V causa algunos dolores de cabeza aquí y no quiero tener que revisar cada lugar que llama a este método.

Entonces la pregunta:

El delegado serviceCall tiene una propiedad Method en el mismo que se describe el método para ejecutar. Esta es una instancia de MethodInfo, que a su vez contiene una propiedad MethodHandle. ¿Estoy en lo cierto al suponer que la propiedad MethodHandle identifica única y consistentemente el método al que se hace referencia?

que cambiaría la envoltura para

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

que encapsula adecuadamente el almacenamiento en caché y preocupaciones clave, & elimina cualquier dependencia de la persona que llama 'hacer lo correcto'.

  • No importa si los cambios MethodHandle entre instancias - el almacenamiento en caché es única por cada instancia
  • No me importa si el MethodHandle no es consistente a través de los clientes - el almacenamiento en caché es por cliente
  • DO cuidado si el MethodHandle no es coherente dentro de una instancia en un cliente, en realidad quiero que se use el caché, en lugar de que cada solicitud genere una nueva llamada de servicio y el caché esté lleno de datos no utilizados
  • DO cuidado si el MethodHandle no es único con en una instancia en un cliente: tengo que estar seguro de que se devuelven los datos correctos (y el tipo) cuando se usa el contenedor.
+0

Por lo que sé, el MethodHandle es una cuestión de metadatos, por lo que podría cambiar al compilar no? No estoy seguro ... Otra forma de eliminar esa posibilidad es construir el caché al inicio o en la primera llamada y usar una variable estática para el caché con el bloqueo apropiado como/si es apropiado. Usaría el contenedor que resume la llamada como lo has mostrado, permitiendo que tu implementación cambie. –

+0

¿Por qué no utilizar MethodInfo en lugar de MethodHandle? El nivel extra de indirección parece innecesario. Pero para responder a su pregunta, tanto MethodInfo como RuntimeMethodHandle son exclusivos de los métodos individuales y son estables durante el tiempo de vida del AppDomain en el que se obtuvieron. – Levi

+0

Para agregar a lo que dijo Levi, MethodHandles no son válidos * en todos los dominios de la aplicación. Es poco probable que entre en juego, pero pensé que iba a entrar. – Amy

Respuesta

2

MSDN, haciendo referencia a la propiedad MethodHandle, dice "esta propiedad es para acceder a las clases administradas desde el código no administrado y no debe invocarse desde el código administrado".

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

Sugerencias:

  • Uso serviceCall.Method.MethodHandle todos modos, ya que se supone que debe ser único dentro del mismo dominio de aplicación.
  • Investigación serviceCall.Method.GetHashCode() para ver si esto funcionaría para usted como su clave de almacenamiento en caché.
  • Cambie el mecanismo de almacenamiento en caché para que sea un diccionario, T> y use serviceCall como la clave de almacenamiento en caché real. (Esto puede no funcionar dependiendo de cómo está llamando el código al método de envoltura.)
Cuestiones relacionadas