Delphi XE10调用DHL API时WSDL生成嵌套数组对象初始化问题
Delphi WSDL导入生成多层级复杂类型的标准使用方法
核心问题原因
Delphi自带的WSDL导入工具生成的SOAP请求类中,所有嵌套的复杂类型属性、数组类型属性默认均为未初始化的nil状态,运行时不会自动创建子对象实例,这是官方设计的标准行为,逐层手动实例化才是符合Delphi SOAP开发规范的实现方式。
多层级结构访问示例
以下为你提到的<Items><Item><Product>层级结构的完整使用示例,首先是WSDL导入后自动生成的典型类型定义:
type // 对应<Product>节点 ProductType = class(TRemotable) private FProductCode: string; FProductName: string; published property ProductCode: string read FProductCode write FProductCode; property ProductName: string read FProductName write FProductName; end; // 对应<Item>节点 ItemType = class(TRemotable) private FProduct: ProductType; FItemId: string; published property ItemId: string read FItemId write FItemId; property Product: ProductType read FProduct write FProduct; end; // 对应<Items>下的Item数组 Array_Of_Item = array of ItemType; // 对应根节点<Items> ItemsType = class(TRemotable) private FItem: Array_Of_Item; published property Item: Array_Of_Item read FItem write FItem; end;
正确的初始化、访问、赋值代码如下:
var Items: ItemsType; begin // 1. 初始化根节点对象 Items := ItemsType.Create; try // 2. 为Item数组分配1个元素长度 SetLength(Items.Item, 1); // 3. 初始化数组内的Item对象 Items.Item[0] := ItemType.Create; // 4. 初始化Item下的Product子对象 Items.Item[0].Product := ProductType.Create; // 此时可正常访问深层属性 Items.Item[0].ItemId := 'ITEM001'; Items.Item[0].Product.ProductCode := 'P001'; Items.Item[0].Product.ProductName := '测试商品'; ShowMessage(Items.Item[0].Product.ProductName); finally // 注意:若将对象若直接传入SOAP接口方法时不需要手动释放,SOAP运行时会在请求完成后自动释放关联对象,手动释放会引发重复释放错误 end; end;
DHL ShipmentOrder场景修复代码
对应你的测试场景,修正后的可正常访问代码如下,注意子对象类名需要和你WSDL导入生成的单元内实际类名保持一致:
var IShipmentorder : Array_Of_ShipmentOrderType; Begin SetLength(IShipmentorder,1); IShipmentorder[0] := shipmentordertype.Create; // 手动初始化Shipment子对象 IShipmentorder[0].Shipment := ShipmentType.Create; // 手动初始化Shipment下的Shipmentdetails子对象 IShipmentorder[0].Shipment.Shipmentdetails := ShipmentDetailsType.Create; // 此时可正常访问所有层级属性 ShowMessage(IShipmentorder[0].UnitName); ShowMessage(IShipmentorder[0].Shipment.UnitName); ShowMessage(IShipmentorder[0].Shipment.Shipmentdetails.UnitName); End;
可选优化方案
如果嵌套层级过多,可自行封装通用递归初始化函数即可简化开发:通过RTTI遍历类的所有published属性,若属性为TRemotable子类且为nil则自动创建实例,数组类型可按需求分配默认长度,实现时注意跳过存在循环引用的属性即可。
内容的提问来源于stack exchange,提问作者Radi
相关产品推荐
相关产品推荐

