如何实现缓存属性?

时间:2011-05-14 02:32:07

标签: c# caching attributes properties

如何实现CacheAttribute,以便我可以在一个地方为所有属性提供相同的逻辑?

我这样做是为了缓存

[TestClass]
public class All
{
    public string N
    {
        get
        {
            var value =
                MemoryCache.Default.Get("Website.Tests.All.N") as string;

            if (value != null)
            {
                return value;
            }

            value = DateTime.Now.ToString("HH:mm:ss.ffff");

            MemoryCache.Default.Add("Website.Tests.All.N", value,
                new CacheItemPolicy
                {
                    AbsoluteExpiration =
                        new DateTimeOffset(DateTime.Now.AddSeconds(5))
                });

            return value;
        }
    }

    [TestMethod]
    public void Extension()
    {
        var start = N;

        Thread.Sleep(1000);

        var end = N;

        Assert.AreEqual(start, end);
    }
}

我想用这个来代替

[TestClass]
public class All
{
    [Cache(Duration=5000)]
    public string N
    {
        get
        {
            return DateTime.Now.ToString("HH:mm:ss.ffff");
        }
    }

    [TestMethod]
    public void Extension()
    {
        var start = N;

        Thread.Sleep(1000);

        var end = N;

        Assert.AreEqual(start, end);
    }
}

有没有办法让这种语法变糖?

1 个答案:

答案 0 :(得分:0)

您似乎希望“接管”该属性的get方法,以便在从您的属性返回“实际”值之前先检查缓存。由于无法在临时基础上执行属性拦截,因此您必须提前计划此工具。

一种方法是使用接口并将类编写到接口。例如,

public interface IAll 
{
    string N { get; set; }
}

现在,您可以使用proxies围绕同样实现此接口的All原始实例创建包装器。此外,由于您现在完全负责该属性,因此只要调用getter,您就可以检查缓存。由于您可以使用PropertyInfo / MethodInfo,因此您可以毫不费力地为每个属性生成唯一键。

因此,每当您实例化All的实例时,您还要实例化此代理,并将All的实例传递给它。该All实例的所有后续用法应该通过代理传递。与任何类工厂实施一样,这要求您放弃使用 new 运算符。

或者,您可以使用虚拟方法而不是接口。