【发布时间】:2021-07-15 17:05:30
【问题描述】:
我正在尝试在 protobuf 消息之间创建一个差异,该差异将适用于代码库中的所有 IMessage 对象(据我所知,每个 protobuf 实现的接口)。
为此,我创建了一个通用方法,它将采用任何IMessage 实现(提供无参数构造函数)并尝试创建一个增量。
public class ProtocolDiffer<T> where T : IMessage, new()
{
public T Diff(T original, T replacement)
{
var delta = new T();
foreach (var fieldDescriptor in replacement.Descriptor.Fields.InFieldNumberOrder())
{
// Obtain the pair of values to compare
var originalFieldValue = fieldDescriptor.Accessor.GetValue(original);
var replacementFieldValue = fieldDescriptor.Accessor.GetValue(replacement);
Console.WriteLine(
$"Is the field {fieldDescriptor.Name.ToUpper()} equal between Original and Replacement? " +
$"{originalFieldValue.Equals(replacementFieldValue)}");
// These fields are equal, jump to the next pair
if (originalFieldValue.Equals(replacementFieldValue)) continue;
// They were not equal
// Is it a simple field?
if (fieldDescriptor.FieldType == FieldType.Message)
{
// Non-basic fields need to be evaluated instead of simply replaced
fieldDescriptor.Accessor.SetValue(delta,
Diff((T)(IMessage) fieldDescriptor.Accessor.GetValue(original),
(T)(IMessage) fieldDescriptor.Accessor.GetValue(replacement)));
}
else
{
fieldDescriptor.Accessor.SetValue(delta, fieldDescriptor.Accessor.GetValue(replacement));
}
}
return delta;
}
...
}
我遇到的问题是递归机制失败,因为最终被处理的对象从通过 protoc 生成的类更改为 RepeatedField 和 Diff 将无法转换对象。
我尝试使用IMessage 作为参数来实例化这个Diff 类,但它没有提供无参数构造函数。我现在正在考虑创建一个实现 IMessage 的类,该类将能够被 protoc 生成的类和 RepeatedField 强制转换,但这仍然需要一些时间,我不确定我是否能够提供必要的首先进行铸造。
最后,这一切都完成了,以便我可以返回两个结构之间的差异,包括原始字段和复杂的字段,例如列表,其想法是递归机制将遍历整个结构,直到它替换每个不同的字段和然后返回仅设置了相同字段的结构。
有没有办法解决强制转换问题,以便我可以继续使用递归机制?
【问题讨论】:
标签: c# generics reflection protocol-buffers