如何实现缓存属性

本文关键字:缓存 属性 实现 何实现 | 更新日期: 2023-09-27 17:56:19

如何实现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);
    }
}

有没有办法使这种语法糖?

如何实现缓存属性

您似乎想"接管"属性的get方法,以便在从属性返回"实际"值之前先检查缓存。 由于无法临时执行财产拦截,因此您必须提前计划此设施。

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

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

现在,您可以使用代理围绕也实现此接口的原始All实例创建包装器。 此外,由于您现在完全负责该属性,因此您可以在调用getter时检查缓存。 由于您可以使用PropertyInfo/MethodInfo,因此您可以轻松为每个属性生成唯一键。

因此,每当您实例化 All 的实例时,您也会实例化此代理,并向其传递 All 的实例。 该 All 实例的所有后续用法都应传递代理。 与任何类工厂实现一样,这要求您放弃使用 new 运算符。

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