2011-09-17 14 views
5

Mam prosty atrybut cache zaimplementowany przy użyciu funkcji postsharp. Kiedy ustawiam politykę pamięci podręcznej, chcę móc ustawić wywołanie zwrotne aktualizacji jak poniżej.Jak mogę wdrożyć UpdateCallback na CacheItemPolicy z innej klasy?

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

To jest w porządku, jeśli tylko chcesz to zrobić:

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

Jednakże chcę, aby móc przejść na delegata/Metoda/nazwy metody i parametrów do dynamicznie i wykonać to. SO Spodziewam się, aby zobaczyć coś takiego (oczywiście składnia jest źle):

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

** * ** * ** * *UPDATE* * * * ****

Mam to działa. Nie jest to najbardziej elegancka metoda, bud działa.

Mój kod obrazu jest następująca:

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

Moja oddzwaniania jest następujący:

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

Czy możesz dołączyć swój kod aspektowy do pytania? Nie rozumiem, co próbujesz osiągnąć. Skąd się wzięła metoda GetCachePolicy i jaki aspekt jest stosowany? –

Odpowiedz

6

Można to zrobić:

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

czy tylko to:

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

Myślę, że możesz to zrobić

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