【发布时间】: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 => 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