2010-05-19 80 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); 
    }