Как рассчитать уникальный хэш-код JObject - PullRequest
0 голосов
/ 11 июля 2019

Я хочу вычислить уникальный хэш-код для Jobject.На основании , поэтому отправьте Я использую метод JTokenEqualityComparer.GetHashCode(JToken token) для вычисления хеш-кода

    [Fact]
    public void GetHashcode()
    {
        JTokenEqualityComparer comp = new JTokenEqualityComparer();

        // arrange
        var obj1 = new JObject();
        obj1.Add("FirstName", "foo");
        obj1.Add("LastName", "bar");

        var hashCode = comp.GetHashCode(obj1);
    }

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

Я использую этот код в основном приложении ASP.NET.Он создает уникальный хеш-код для объектов JOb с теми же свойствами и значениями, однако, как только пул приложений перерабатывается, он создает новый хэш-код для того же JObject.

Как создать уникальный хэш-код для объекта JObject, который имеет те же свойстваа ценности?

Таким образом, если есть 3 экземпляра объектов JObject, которые имеют одинаковые свойства и значения, их хеш-код должен быть одинаковым, независимо от компьютера, времени и класса, который вычисляет хеш-код.

1 Ответ

0 голосов
/ 12 июля 2019

Вы можете использовать что-то вроде этого.Хотя я не уверен, если это является окончательным с точки зрения JSON - не пробовал массивы, например.Но я верю, что вы сможете адаптировать его.:)

[Fact]
public void GetHashcode() {
    var o1 = new JObject();
    o1.Add("FirstName", "foo");
    o1.Add("LastName", "bar");

    var o2 = new JObject();
    o2.Add("Lorem", 123);
    o2.Add("Ipsum", DateTime.Now.Date);

    o1.Add("inner", o2);

    var hashCode = ComputeHashCode(o1);
}

private static int ComputeHashCode(JToken value)
{
    if (value is null)
    {
        return 0;
    }

    var queue = new Queue<JProperty>();
    foreach (JProperty prop in value)
    {
        queue.Enqueue(prop);
    }
    if (queue.Count == 0)
    {
        return 0;
    }

    int hash = 17;
    while (queue.Count > 0)
    {
        JProperty item = queue.Dequeue();
        if (item.Value.HasValues)
        {
            foreach (JProperty prop in item.Value)
            {
                queue.Enqueue(prop);
            }
        }
        else
        {
            // Hash code combination taken from here: https://stackoverflow.com/a/263416/8088324
            unchecked
            {
                hash = hash * 23 + ComputeHashCodeCore(item.Name);
                hash = hash * 23 + ComputeHashCodeCore(item.Value.ToString());
            }
        }
    }
    return hash;
}

// Stable hash code for string taken from here: https://stackoverflow.com/a/36845864/8088324
private static int ComputeHashCodeCore(string str)
{
    unchecked
    {
        int hash1 = 5381;
        int hash2 = hash1;

        for (int i = 0; i < str.Length && str[i] != '\0'; i += 2)
        {
            hash1 = ((hash1 << 5) + hash1) ^ str[i];
            if (i == str.Length - 1 || str[i + 1] == '\0')
                break;
            hash2 = ((hash2 << 5) + hash2) ^ str[i + 1];
        }

        return hash1 + (hash2 * 1566083941);
    }
}
...