请求帮助将C#代码移植到Delphi,解决TArray泛型相关问题
C#数组序列化逻辑移植到Delphi的TArray泛型处理问题
我在把一段C#代码移植到Delphi时,遇到了TArray泛型类型相关的问题。目前已经完成了Int32、Int64、UInt32等基础类型的WriteValue逻辑实现,但在处理数组部分时卡住了。附上C#原代码和我写的不完整Delphi代码,求WriteVector后续代码的正确写法。
C#原代码
internal static void WriteValue(object value, Type valueType) { var type = value.GetType(); switch (Type.GetTypeCode(type)) { // 以下基础类型已在Delphi中实现 case TypeCode.Int32: Write((int)value); break; case TypeCode.Int64: Write((long)value); break; case TypeCode.UInt32:Write((uint)value); break; case TypeCode.UInt64:Write((ulong)value); break; case TypeCode.Double:Write((double)value); break; case TypeCode.Object: if (type.IsArray) // 问题出在这里 WriteVector((Array)value); break; default: break; } } internal static void WriteVector(Array array) { if (array == null) { return; } int count = array.Length; // 保存数组长度 var elementType = array.GetType().GetElementType(); for (int i = 0; i < count; i++) WriteValue(array.GetValue(i), elementType); }
我的Delphi代码(不完整)
// 我的Delphi代码 procedure WriteValue(Value: TValue; valueType: PTypeInfo); begin case Value.Kind of tkArray: WriteVector(Value.AsType<TArray>); end; end; procedure WriteVector(array: TArray); var count: Integer; i: Integer; begin if array = nil then begin Exit; end; // count := Length(array); // 保存count值 // 后续代码该怎么写? end;
解决方案
Delphi中的TArray是泛型容器,不能直接作为无类型参数传递,且Delphi区分静态数组(tkArray)和动态数组(tkDynArray),需要结合RTTI来实现类似C#的通用数组处理逻辑。以下是修正后的完整代码:
修正后的WriteValue
procedure WriteValue(Value: TValue; ValueType: PTypeInfo); begin case Value.Kind of tkInteger: Write(Value.AsInteger); tkInt64: Write(Value.AsInt64); tkUInt32: Write(Value.AsUInt32); tkUInt64: Write(Value.AsUInt64); tkFloat: Write(Value.AsDouble); tkArray, tkDynArray: // 同时处理静态和动态数组 WriteVector(Value); // 其他类型可根据需求扩展 end; end;
完整实现的WriteVector
uses System.Rtti, System.TypInfo; procedure WriteVector(const ArrayValue: TValue); var Context: TRttiContext; ArrayType: TRttiArrayType; DynArrayType: TRttiDynamicArrayType; ElementType: PTypeInfo; I: Integer; ElementValue: TValue; ArrayLength: Integer; begin if not ArrayValue.IsArray then Exit; // 获取数组长度和元素类型 case ArrayValue.Kind of tkArray: begin ArrayType := Context.GetType(ArrayValue.TypeInfo) as TRttiArrayType; // 计算一维静态数组的长度 ArrayLength := ArrayType.Dimensions[0].Range.Max - ArrayType.Dimensions[0].Range.Min + 1; ElementType := ArrayType.ElementType.Handle; end; tkDynArray: begin DynArrayType := Context.GetType(ArrayValue.TypeInfo) as TRttiDynamicArrayType; ArrayLength := DynArrayType.GetLength(ArrayValue.GetReferenceToRawData); ElementType := DynArrayType.ElementType.Handle; end; else Exit; end; // 写入数组长度(假设Write已实现Integer类型的写入) Write(ArrayLength); // 遍历数组元素,递归调用WriteValue for I := 0 to ArrayLength - 1 do begin ElementValue := ArrayValue.GetArrayElement(I); WriteValue(ElementValue, ElementType); end; end;
关键说明
- 数组类型区分:Delphi需要分别处理静态数组(
tkArray)和动态数组(tkDynArray),两者的长度获取方式不同 - RTTI的使用:通过
TRttiContext获取数组的类型元数据,包括元素类型、数组维度/长度 - 元素遍历:使用
TValue.GetArrayElement直接获取数组中指定索引的元素,无需手动转换类型 - 递归调用:和C#逻辑一致,对每个数组元素递归调用
WriteValue完成序列化
内容的提问来源于stack exchange,提问作者Sdean
相关产品推荐
相关产品推荐

