C# C、 为对象数组生成常量键

C# C、 为对象数组生成常量键,c#,valueconverter,C#,Valueconverter,我想在缓存中保存一个具有常量键的对象 public TItem Set<TItem>(string key, TItem value) { return = _memoryCache.Set(key, value); } 我使用如下函数获取对象: public TItem Get( TPrimaryKey id, params object[] args, bool byPassCach

我想在缓存中保存一个具有常量键的对象

    public TItem Set<TItem>(string key, TItem value)
    {
        return = _memoryCache.Set(key, value);
    }
我使用如下函数获取对象:

    public TItem Get(
        TPrimaryKey id,
        params object[] args,
        bool byPassCaching = false
    )
    {
        if (byPassCaching || !_cacheManager.TryGetValue<TItem>(GetKey(id, args), out TItem result)){
           item = [FUNCTION TO GET ITEM];
           _cacheManager.Set(GetKey(id, args), item)
        }
        return item;
    }
我想为TItem、Id int和一些params对象[]args生成一个常量键

以下是生成常量键的函数:

    internal static string GetKey<TItem>(int id, params object[] args)
    {
        return string.Format("{0}#{1}[{2}]", typeof(TItem).FullName, id, args?[FUNCTION TO CALL]);
    }
[要调用的函数]是我正在寻找的函数

所以下次我用相同的参数调用函数时,我将使用相同的键

例如

GetKey<MyClass>(1, null) => "MyApp.MyClass#1[]"
GetKey<MyClass>(1, "Hello", "World") => "MyApp.MyClass#1[sdas5d1as5d4sd8]"
GetKey<MyClass>(1, "Hello", "World") => "MyApp.MyClass#1[sdas5d1as5d4sd8]"
GetKey<MyClass>(1, item => item.Include(s => s.Categories)) => "MyApp.MyClass#1[asdasdasd87wqw]"
起初,我想使用GetHashCode,但生成的int总是不同的

internal static string GetKey<TEntity>(int id, params object[] args)
{
    return string.Format("{0}#{1}[{2}]", typeof(TEntity).FullName, id, ArrayHash(args));
}

static string ArrayHash(params object[] values)
{
    return BitConverter.ToString(BitConverter.GetBytes(ArrayHashCode(values))).Replace("-", "").ToLowerInvariant();
}

static int ArrayHashCode(params object[] values)
{
    if (values == null || values.Length == 0) return 0;
    var value = values[0];
    int hashCode = value == null ? 0 : value.GetHashCode();
    for (int i = 1; i < values.Length; i++)
    {
        value = values[i];
        unchecked
        {
            hashCode = (hashCode * 397) ^ (value == null ? 0 : value.GetHashCode());
        }
    }
    return hashCode;
}

我该怎么做呢?

我认为GetHashCode是您所需要的;您是在数组上调用GetHashCode,还是在数组的每个成员上调用它?你想做后者

以下内容应与您想要的内容相似;如果参数为null或空,或充满null对象,则代码将为00000000

否则,如果参数相同,则结果哈希将相同。如果参数的顺序或值不同,则散列将不同

internal static string GetKey<TEntity>(int id, params object[] args)
{
    return string.Format("{0}#{1}[{2}]", typeof(TEntity).FullName, id, ArrayHash(args));
}

static string ArrayHash(params object[] values)
{
    return BitConverter.ToString(BitConverter.GetBytes(ArrayHashCode(values))).Replace("-", "").ToLowerInvariant();
}

static int ArrayHashCode(params object[] values)
{
    if (values == null || values.Length == 0) return 0;
    var value = values[0];
    int hashCode = value == null ? 0 : value.GetHashCode();
    for (int i = 1; i < values.Length; i++)
    {
        value = values[i];
        unchecked
        {
            hashCode = (hashCode * 397) ^ (value == null ? 0 : value.GetHashCode());
        }
    }
    return hashCode;
}

请注意,如果params数组包含对象,它们也需要有一个适当的GetHashCode实现。

IEntity如何融入其中?请举例说明,这样我们就可以提供帮助。谢谢,我删除了无用的IEntity,只关注KeyGeneration+我添加了一些示例。这感觉像是一个XY问题。为什么要这样做?如果您解释了使用这些“常量键”的目的,这将非常有帮助。感谢您的评论,有没有其他方法可以不用重写GetHasCode就可以这样做?如果您将实体作为参数传递,那么它们应该实现GetHashCode。否则,您可以编写一个方法,该方法可以从实体的属性生成哈希代码,但这将涉及反射,性能可能开始成为一个问题。避免使用GetHashCode有什么特别的原因吗?参数可以是很多东西,一个用于筛选的func,一个用于包含数据的func。最后,我想创建一个CacheRepository和CacheUnitOfWork。我知道,这个想法并不完美,但我对挑战更感兴趣。只需更改我的代码,对值类型使用GetHashCode,并为funcs计算一个哈希代码。我不知道您是要调用函数并散列结果,还是要标识函数。缺少很多。如果内置类型GetHashCode实现在将来发生更改,这可能是一个问题-。