基于方法名称和参数值缓存键构造

Mon*_*der 8 c# hash caching dictionary

我决定在我们的一个应用程序中实现缓存外观 - 目的是最终减少网络开销并限制db命中量.我们正在使用Castle.Windsor我们IoC Container,我们决定Interceptors使用System.Runtime.Caching命名空间在我们的服务层之上添加缓存功能.

在这一刻,我无法弄清楚什么是构建它的最佳方法cache key.目标是区分不同的方法,并且还包括传递的参数值 - 这意味着这两个方法调用应该缓存在两个不同的键下:

IEnumerable<MyObject> GetMyObjectByParam(56); // key1
IEnumerable<MyObject> GetMyObjectByParam(23); // key2
Run Code Online (Sandbox Code Playgroud)

现在我可以看到两种可能的实现:

选项1: 装配| 班级| 方法返回类型| 方法名称| 参数类型| 参数哈希码

"MyAssembly.MyClass IEnumerable<MyObject> GetMyObjectByParam(long) { 56 }";
Run Code Online (Sandbox Code Playgroud)

选项2: MD5或SHA-256基于方法的完全限定名称和传递的参数值计算散列

string key = new SHA256Managed().ComputeHash(name + args).ToString();
Run Code Online (Sandbox Code Playgroud)

我正在考虑第一个选项,因为第二个选项需要更多的处理时间 - 另一方面,第二个选项强制执行所有生成的键的完全相同的"长度".

假设第一个选项将为使用复杂参数类型的方法生成唯一键是否安全?或者也许有一种完全不同的做法?

帮助和意见将受到高度赞赏!

Mon*_*der 5

基于我在这里这里找到的一些非常有用的链接,我决定或多或少地实现它:

public sealed class CacheKey : IEquatable<CacheKey>
{
    private readonly Type reflectedType;
    private readonly Type returnType;
    private readonly string name;
    private readonly Type[] parameterTypes;
    private readonly object[] arguments;

    public User(Type reflectedType, Type returnType, string name, 
        Type[] parameterTypes, object[] arguments)
    {
        // check for null, incorrect values etc.

        this.reflectedType = reflectedType;
        this.returnType = returnType;
        this.name = name;
        this.parameterTypes = parameterTypes;
        this.arguments = arguments;
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as CacheKey);
    }

    public bool Equals(CacheKey other)
    {
        if (other == null)
        {
            return false;
        }

        for (int i = 0; i < parameterTypes.Count; i++)
        {
            if (!parameterTypes[i].Equals(other.parameterTypes[i]))
            {
                return false;
            }
        }

        for (int i = 0; i < arguments.Count; i++)
        {
            if (!arguments[i].Equals(other.arguments[i]))
            {
                return false;
            }
        }

        return reflectedType.Equals(other.reflectedType) &&
           returnType.Equals(other.returnType) &&
           name.Equals(other.name);
    }

    private override int GetHashCode()
    {
        unchecked
        {
            int hash = 17;

            hash = hash * 31 + reflectedType.GetHashCode();
            hash = hash * 31 + returnType.GetHashCode();
            hash = hash * 31 + name.GetHashCode();

            for (int i = 0; i < parameterTypes.Count; i++)
            {
                hash = hash * 31 + parameterTypes[i].GetHashCode();
            }

            for (int i = 0; i < arguments.Count; i++)
            {
                hash = hash * 31 + arguments[i].GetHashCode();
            }

            return hash;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上这只是一个一般性的想法 - 上面的代码可以很容易地重写为一个更通用的版本,其中包含一个集合Fields- 必须对集合的每个元素应用相同的规则。我可以分享完整的代码。