2010-05-19 81 views
1

在C#中,是否可以修飾帶註釋的方法以使用方法的返回值填充緩存對象?使用ASP.NET Caching API通過C#中的方法註釋

目前我使用下面的類來緩存數據對象:

public class SiteCache 
{ 
// 7 days + 6 hours (offset to avoid repeats peak time) 
    private const int KeepForHours = 174; 
    public static void Set(string cacheKey, Object o) 
    { 
     if (o != null) 
      HttpContext.Current.Cache.Insert(cacheKey, o, null, DateTime.Now.AddHours(KeepForHours), TimeSpan.Zero); 
    } 
    public static object Get(string cacheKey) 
    { 
     return HttpContext.Current.Cache[cacheKey]; 
    } 
    public static void Clear(string sKey) 
    { 
     HttpContext.Current.Cache.Remove(sKey); 
    } 
    public static void Clear() 
    { 
     foreach (DictionaryEntry item in HttpContext.Current.Cache) 
     { 
      Clear(item.Key.ToString()); 
     } 
    } 
} 

的方法我想緩存我這樣做:

[DataObjectMethod(DataObjectMethodType.Select)] 
public static SiteSettingsInfo SiteSettings_SelectOne_Name(string Name) 
{ 
    var ck = string.Format("SiteSettings_SelectOne_Name-Name_{0}-", Name.ToLower()); 
    var dt = (DataTable)SiteCache.Get(ck); 
    if (dt == null) 
    { 
     dt = new DataTable(); 
     dt.Load(ModelProvider.SiteSettings_SelectOne_Name(Name)); 
     SiteCache.Set(ck, dt); 
    } 
    var info = new SiteSettingsInfo(); 
    foreach (DataRowView dr in dt.DefaultView) 
     info = SiteSettingsInfo_Load(dr); 
    return info; 
} 

是否有可能這些問題分開,像這樣:(注意新註釋)

[CacheReturnValue] 
[DataObjectMethod(DataObjectMethodType.Select)] 
public static SiteSettingsInfo SiteSettings_SelectOne_Name(string Name) 
{ 
    var dt = new DataTable(); 
    dt.Load(ModelProvider.SiteSettings_SelectOne_Name(Name)); 

    var info = new SiteSettingsInfo(); 
    foreach (DataRowView dr in dt.DefaultView) 
     info = SiteSettingsInfo_Load(dr); 
    return info; 
} 

回答

0

是的,你需要使用一個過程,如PostSharp爲您提供執行方法屬性代碼之前/之後執行的功能。

當前版本的PostSharp是免費的,如果你不需要類/組件級別的屬性。

0

你的想法很好,但仍然不是那麼容易。我自己也想過類似的事情。

創建一個屬性很容易,但是 ......實際上,屬性本身並沒有做任何事情。

您將需要使用AOP(面向方面​​編程)來實現這一點。有很多好的框架可以讓你以某種方式做到這一點。

他們基本上是由物體周圍建立所謂的「代理」的工作 - 他們從你的類型派生progmatically,實現在你的代碼的某些東西,然後返回新的類型。
其中一些在運行中執行此操作,另一些則在編譯後使用ILmerge和其他內容來操作代碼。

基本上,您必須使用Reflection來檢索哪些項目使用您的屬性,並對此做一些事情。 MSDN: Attributes

所以,這裏是你必須做的:

  • 創建描述您需要實現
  • 創建使用屬性一類什麼樣的屬性自定義屬性。它應該檢索哪些項目使用該屬性,然後做一些相關的事情。

還有更多的東西:attributes tutorial,creating custom attributes。您可以搜索並查找關於該主題的更多信息。

+0

筆者從斯科特Hanselman的約AOP播客的啓發。所以驗證控件在MVC中工作,然後如果註釋不做任何事情? – craigmoliver 2010-05-19 21:43:29

+0

註解本身不做任何事情。但驗證框架確實檢查你的屬性具有哪些屬性,並且包含關於如何處理它們的行爲。 (編輯我的帖子澄清。) – Venemo 2010-05-19 22:06:57

0

它不像使用屬性那麼優雅,但是您也可以將一個方法添加到緩存容器,該方法將委託作爲參數並封裝邏輯本身。

public class SiteCache 
{ 

    public static T Retrieve<T>(Delegate d, params object[] methodParameters) 
    { 
     string key = d.Method.ReflectedType + "#" + d.Method.Name; 
     for (int i = 0; i < methodParameters.Length; i++) 
     { 
      key += methodParameters[i].ToString(); 
     } 

     object retVal = Get(key); 
     if (retVal == null) 
     { 
      retVal = d.DynamicInvoke(methodParameters); 
      Set(key, retVal); 
     } 
     return (T) retVal; 
    } 
    // the rest of your class goes here 

然後,你可以把它在你的背後ASP.NET代碼:

delegate string DoStuffDelegate(string key); 

    protected void Page_Load(object sender, EventArgs e) 
    { 

     string s1 = SiteCache.Retrieve<string>(new DoStuffDelegate(DoStuff), "my key"); 
     string s2 = SiteCache.Retrieve<string>(new DoStuffDelegate(DoStuff), "my key"); 

     //at this point, s1 will be the same as s2 
    } 

    int doStuffCount = 0; 
    private string DoStuff(string key) 
    { 
     doStuffCount++; 
     return string.Format("Calling do stuff with key '{0}' - count = {1}", key, doStuffCount); 
    }