2015-10-15 52 views
1

我最近開始使用PostSharp,主要是因爲我想實現方法緩存。我發現如何做到這一點幾個例子,但所有這些例子都是基於執行結果應該使用緩存的高速緩存方法,屬性和裝飾方法:在運行時使用PostSharp自定義註冊方法緩存

我會喜歡以一種方式實現緩存,以便能夠根據配置爲運行時間中的每種方法設置一些額外的參數。例如,我想註冊一個具有單獨過期時間的特定方法緩存,但在代碼編譯期間我不知道該值。

我不怎麼做的事情是如何在運行時做到這一點,而不用裝飾方法。

+0

PostSharp可以添加緩存,你的方法的唯一方法是通過在編譯時編織的IL代碼。如果您需要在運行時控制緩存行爲,則可以從截取代碼內檢查當前配置。例如,如果尚未爲此特定方法啓用高速緩存,則可以立即繼續進行原始方法調用。當然,這不會幫助您避免裝飾方法。 – AlexD

回答

1

這應該很簡單,儘管你需要編寫你需要的細節代碼,下面是重要的細節,粘貼我的代碼,所以一些變量是我們的習慣,相應地修改它們。您需要將屬性應用[ViewrCache]的相關方法後創建下面的代碼,它會在修改方法IL因此在運行時

創建一個從PostSharp.Aspects.MethodInterceptionAspect擴展的自定義緩存屬性如下:

[Serializable] 
    public sealed class ViewrCacheAttribute : MethodInterceptionAspect 

類變量:從配置文件

//緩存過期

private static readonly int CacheTimeOut = Convert.ToInt32(WebConfigurationManager.AppSettings[CacheSettings.CacheTimeOutKey]); 

//參數從緩存鍵

private string[] IgnoreParameters { get; set; } 

覆蓋被忽略的方法OnInvoke(MethodInterceptionArgs args)如下:

// My custom implementation that you may want to change 
public override void OnInvoke(MethodInterceptionArgs args) 
     { 
      // Fetch standard Cache 
      var cache = MemoryCache.Default; 

      // Fetch Cache Key using the Method arguments 
      string cacheKey = GetCacheKey(args); // Code pasted below 

      var cacheValue = cache.Get(cacheKey); 

      if (cacheValue != null) 
      { 
       args.ReturnValue = cacheValue; 

       return; 
      } 
      ReloadCache(cacheKey, args); 
     } 

//獲取緩存鍵方法

private string GetCacheKey(MethodInterceptionArgs args) 
     { 
      //need to exclude paging Parameters from Key 

      var builder = new StringBuilder(); 

      var returnKey = new ViewrCacheKey { CallingMethodFullName = args.Method.ToString() }; 

      // Loop through the Call arguments/parameters 
      foreach (var argument in args.Arguments) 
      { 
       if (argument != null) 
       { 
        if ((IgnoreParameters == null) || 
         (IgnoreParameters != null && !IgnoreParameters.Contains(argument.ToString()))) 
         builder.Append(JsonConvert.SerializeObject(argument)); 
       } 
      } 

      returnKey.ControllerHash = builder.ToString(); 

      return JsonConvert.SerializeObject(returnKey); 
     } 

//刷新緩存

private Object ReloadCache(string cacheKey, MethodInterceptionArgs args) 
     { 
      //call the actual Method 
      base.OnInvoke(args); 

      //Save result into local cache 
      InsertCache(cacheKey, args.ReturnValue); 
      return args.ReturnValue; 
     } 

//插入緩存

private void InsertCache(string key, object value) 
     { 
      // Setting Cache Item Policy 
      var policy = new CacheItemPolicy 
      { 
       SlidingExpiration = new TimeSpan(0, 0, CacheTimeOut) 
      }; 

      // sliding Expiration Timeout in Seconds 
      ObjectCache cache = MemoryCache.Default; 

      // Set the key,value in the cache 
      cache.Set(key, value, policy); 
     } 

// ViewR緩存鍵

public class ViewrCacheKey 
    { 
     /// <summary> 
     /// 
     /// </summary> 
     public string CallingMethodFullName { get; set; } 

     /// <summary> 
     /// 
     /// </summary> 
     public string ControllerHash { get; set; } 
    } 
+0

謝謝你的例子,但它不回答我的問題。您創建了與我在帖子中放置的鏈接類似的示例。我的問題是不同的。我需要在運行時將方法註冊到緩存機制中,而不是用屬性裝飾它們。 –

+0

您計劃在運行時爲給定方法添加緩存方面,但如果相關數據不在緩存中,則在實際方法邏輯執行之前,通過在裝入方法的運行時插入必要的IL以執行必要的IL工作。讓我檢查不確定Post Sharp使用聲明性屬性的工作可以在運行時附加到方法 –

+0

可幫助的幾個鏈接: http://doc.postsharp.net/iaspectprovider http:// stackoverflow。 com/questions/27693438/postsharp-how-to-know-at-runtime-if-a-aspect-was-applied-to-a-method http://stackoverflow.com/questions/2461862/adding -code到最開始-結束方法-在運行時動態地 –