【问题标题】:generate predictable unique string based on a generic objects content基于通用对象内容生成可预测的唯一字符串
【发布时间】:2017-12-10 17:51:57
【问题描述】:

故事

我正在尝试编写一个通用方法,它结合属性名称、类型和内容值来为持有的值生成一个唯一字符串 > 由传递的对象。

这个想法是根据生成的字符串序列生成唯一的 SHA3-512 哈希可用于在通用基础上比较对象通过查看他们的内容


示例

假设我们有一个这样的类...

class MyClass {
    private Int32 Id = 5;
    public String Name = "some string";
    protected DateTime CreateDate = DateTime.Parse("2017-08-21 15:00:07");
}

...以及上面提到的生成唯一字符串的方法

static String GetContentString<T>(T obj) where T : class {
  ...
}

理论上这应该有点像这样

var myObj = new MyClass();
var uniqueContentString = GetContentString(myObj);

Console.WriteLine(uniqueContentString);
>>> Id:Int32:5$Name:String:some string$CreateDate:DateTime:2017-08-21 15:00:07

问题

我在构建GetContentString 方法时遇到了困难。 这是我已经拥有的

Object obj = ... // given object
Type type = obj.GetType();
IList<PropertyInfo> propertyInfos = type.GetProperties().Where(x => x.CanRead).ToList(); // Marker #2

StringBuilder sb = new StringBuilder();
foreach (PropertyInfo pi in propertyInfos)
{
    sb.Append(pi.Name);
    sb.Append(":");
    sb.Append(pi.PropertyType.Name);
    sb.Append(":");
    sb.Append(pi.GetValue(obj) ?? "[ISNULL]"); // Marker #1
    sb.Append(":");
}

return sb.ToString();

我尝试为几种不同类型的值运行该方法,例如 "some string"1234 (Int32),但遇到了一些问题。

给定一个字符串,方法调用会抛出 System.Reflection.TargetParameterCountException 类型的异常,并在 #1 处抛出消息 Parameter count mismatch。我发现可以将可选索引传递给pi.GetValue(..) 的重载版本,然后返回单个字母之一。 但是你怎么知道什么时候停止?如果你调用一个不存在的索引,它会抛出System.Reflection.TargetInvocationException 类型的异常。 如何使用反射获取字符串对象的值?

给定一个整数值,方法调用在#2 处找不到任何属性。这带来了如何使用反射获取整数对象的值的问题?

还有一些一般性问题; 你们认为这是获得唯一字符串的好方法吗?反思是要走的路吗?是否有可能为这个问题写一个通用的解决方案

【问题讨论】:

  • 是的,有可能(解决方案很大,但并不难)。但首先有几个问题:你为什么需要这个? GetHashCode() 有问题吗?为什么选择 SHA256?
  • 使用.Where(p =&gt; p.GetIndexParameters().Length == 0) 过滤掉索引属性可能会更容易,因为您确实没有可靠的方法为它们提供值。
  • 根据定义,SHA3-512 允许创建冲突并且不能是“唯一的”。之后你打算用你的哈希做什么? Explain what your goal is, not just what you are doing.
  • @DourHighArch 正如我所说,目标是根据内容比较对象
  • @tobias,所有散列定义为cannot be unique。想一想,他们采用可变长度数据并返回固定大小的输出,因此在数学上他们must allow collisions。密码不必是唯一的,它们的哈希值也不必是唯一的。您提出的建议可能行不通;如果您解释了您想要什么以及为什么您认为哈希会这样做,我们可能会为您提供帮助。

标签: c# generics reflection


【解决方案1】:

不考虑反射,用 .net 框架能够做到的 JSON 序列化怎么样? 反射不是非常快的东西,您会在第一个未处理的异常时遇到问题。

然后,如果您的对象可以包含复杂的属性,您应该递归地执行此操作,这不是 json 序列化的问题!

【讨论】:

  • 这确实是一种非常有趣的方法,实际上可能是解决这个问题的方法。我去试试
  • 请记住,无论如何 JSON 序列化最终都会在幕后使用反射。
  • @BradleyUffner 我不介意是否使用反射,只要它有效
  • 肯定 json 序列化使用反射,但在一些 nuget 包(如 newtonsoft 或 .net 框架)中,可能会比手写更有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-02
  • 1970-01-01
  • 1970-01-01
  • 2020-07-30
  • 2021-07-08
  • 2019-09-26
  • 1970-01-01
相关资源
最近更新 更多