2011-09-17 8 views
5

Ho un semplice attributo Cache implementato usando PostPlay. Quando imposto il criterio della cache, desidero essere in grado di impostare un callback di aggiornamento come di seguito.Come posso implementare un UpdateCallback su un CacheItemPolicy da un'altra classe?

private static CacheItemPolicy GetCachePolicy(CacheType type, int expiry) 
    { 
     var policy = new CacheItemPolicy(); 

     switch (type) 
     { 
      case (CacheType.Absolute): 
       policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(expiry); 
       policy.UpdateCallback = new CacheEntryUpdateCallback(UpdateHandler); 
       break; 
      case (CacheType.Sliding): 
       policy.SlidingExpiration = new TimeSpan(0, 0, 0, expiry); 
       break; 
     } 

     return policy; 
    } 

Questo va bene se voglio solo fare questo:

private static void UpdateHandler(CacheEntryUpdateArguments arguments) 
    { 
     throw new NotImplementedException(); 
    } 

Tuttavia, voglio essere in grado di passare in un/metodo/nome e parametri di metodo delegato in modo dinamico ed eseguire quello. SO mi sarei aspettato di vedere qualcosa di simile (ovviamente sintassi è sbagliato):

private static CacheItemPolicy GetCachePolicy(CacheType type, int expiry Func<?,?> method) 
    { 
     var policy = new CacheItemPolicy(); 

     switch (type) 
     { 
      case (CacheType.Absolute): 
       policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(expiry); 
       policy.UpdateCallback = new CacheEntryUpdateCallback(method); 
       break; 
      case (CacheType.Sliding): 
       policy.SlidingExpiration = new TimeSpan(0, 0, 0, expiry); 
       break; 
     } 

     return policy; 
    } 

** * *** *** *AGGIORNAMENTO* * * * ****

Ho funzionato. Non è il metodo più elegante, funziona.

Il mio codice Aspect è il seguente:

[Serializable] 
public sealed class CacheAttribute : MethodInterceptionAspect 
{ 
    private readonly CacheType m_cacheType; 
    private readonly int m_expiry; 
    private readonly bool m_useCallBack; 
    private KeyBuilder m_keyBuilder; 

    public KeyBuilder KeyBuilder 
    { 

     get { return m_keyBuilder ?? (m_keyBuilder = new KeyBuilder()); } 

    } 

    public CacheAttribute(CacheType cacheType, int expiry, bool useCallBack) 
    { 
     m_cacheType = cacheType; 
     m_expiry = expiry; 
     m_useCallBack = useCallBack; 
    } 

    public CacheAttribute(CacheType cacheType, int expiry) 
    { 
     m_cacheType = cacheType; 
     m_expiry = expiry; 
     m_useCallBack = false; 
    } 


    //Method executed at build time. 

    public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo) 
    { 

     KeyBuilder.MethodParameters = method.GetParameters(); 

     KeyBuilder.MethodName = string.Format("{0}.{1}", method.DeclaringType.FullName, method.Name); 

    } 

    public override void OnInvoke(MethodInterceptionArgs context) 
    { 
     object value; 


     string key = KeyBuilder.BuildCacheKey(context, context.Arguments); 
     if (!CacheHelper.Get(key, out value)) 
     { 
      // Do lookup based on caller's logic. 
      context.Proceed(); 
      value = context.ReturnValue; 
      var cacheObject = new CacheObject {CacheValue = value, Context = context}; 
      CacheHelper.Add(cacheObject, key, m_cacheType, m_expiry, m_useCallBack); 
     } 

     context.ReturnValue = value; 
    } 
} 

mio richiamata è la seguente:

private static void UpdateHandler(CacheEntryUpdateArguments arguments) 
    { 
     CacheObject cacheObject = (CacheObject)arguments.Source.Get(arguments.Key); 
     cacheObject.Context.Proceed(); 
     cacheObject.CacheValue = cacheObject.Context.ReturnValue; 

     CacheItem updatedItem = new CacheItem(arguments.Key, cacheObject); 
     arguments.UpdatedCacheItem = updatedItem; 
    } 
+0

Potresti includere il tuo codice di aspetto nella domanda? Non capisco cosa stai cercando di ottenere. Da dove viene chiamato il metodo GetCachePolicy e quale aspetto viene applicato dove? –

risposta

6

Si può fare questo:

private static CacheItemPolicy GetCachePolicy(CacheType type, int expiry, 
            Action<CacheEntryUpdateArguments> method) 
{ 
    ... 
    policy.UpdateCallback = (a) => method(a); 
    ... 
    return policy; 
} 

O semplicemente questo:

private static CacheItemPolicy GetCachePolicy(CacheType type, int expiry, 
              CacheEntryUpdateCallback method) 
{ 
    ... 
    policy.UpdateCallback = method; 
    ... 
    return policy; 
} 
0

Penso che si possa fare questo

` 
    private static CacheItemPolicy GetCachePolicy(CacheType type, int expiry, Func method) 
    { 
     var policy = new CacheItemPolicy(); 

     switch (type) 
     { 
      case (CacheType.Absolute): 
        Action updateCallBackHandler = null; 
        updateCallBackHandler = delegate(CacheEntryUpdateArguments arguments) 
        {       
         var newData = FetchYourDataWithCustomParameters(); 

         arguments.UpdatedCacheItem = new CacheItem(arguments.Key, newData); 
         arguments.UpdatedCacheItemPolicy = new CacheItemPolicy() 
         { 
          AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(expiry), 
          UpdateCallback = new CacheEntryUpdateCallback(updateCallBackHandler) 
         }; 
        }; 

        policy.UpdateCallback = new CacheEntryUpdateCallback(updateCallBackHandler); 

       break; 
      case (CacheType.Sliding): 
       policy.SlidingExpiration = new TimeSpan(0, 0, 0, expiry); 
       break; 
     } 

     return policy; 
    } 
'