использование ASP.NET Caching API с помощью аннотаций методов в C # - PullRequest
1 голос
/ 20 мая 2010

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

Ответы [ 3 ]

0 голосов
/ 20 мая 2010

Ваша идея хороша, но все же, это не так просто. Я сам тоже думал о чем-то похожем.

Довольно просто создать атрибут, , но ... на самом деле атрибут сам по себе ничего не делает.

Вам нужно будет использовать AOP (Аспектно-ориентированное программирование) для достижения этой цели. Существует множество хороших фреймворков, которые позволяют вам каким-то образом это делать.

Они в основном работают, создавая так называемые "прокси" вокруг объектов - они наследуются от вашего типа программно, реализуют некоторые вещи вокруг вашего кода, а затем возвращают новый тип.
Некоторые из них делают это на лету, в то время как другие используют ILmerge и другие средства для управления вашим кодом после компиляции.

По сути, вы должны использовать Reflection, чтобы узнать, какие элементы используют ваш атрибут, и что-то с этим сделать. MSDN: атрибуты

Итак, вот что вам нужно сделать:

  • Создайте пользовательский атрибут со свойствами, которые описывают то, что вам нужно для достижения
  • Создайте класс, который использует атрибут. Он должен узнать, какие элементы используют атрибут, а затем что-то с этим сделать.

Есть еще материал: учебник по атрибутам , создание пользовательских атрибутов . Вы можете искать и найти еще больше о теме.

0 голосов
/ 20 мая 2010

Это не так элегантно, как использование атрибута, но вы также можете добавить метод в ваш контейнер кэша, который принимает делегат в качестве параметра и инкапсулирует саму логику.

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);
    }
0 голосов
/ 20 мая 2010

Да, вам нужно использовать такой процесс, как PostSharp , чтобы дать вам возможность выполнять код до / после для атрибутов метода.

Текущая версия PostSharp БЕСПЛАТНА, если вам не нужны атрибуты уровня класса / сборки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...