WCF 服务中的嵌套结构 returns 为空
Nested struct returns empty from WCF service
我需要 return 来自 WCF 服务的以下嵌套数据作为调用的 out
参数:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct PrinterInfo {
public InkInfo Cyan;
public InkInfo Magenta;
public InkInfo Yellow;
public InkInfo Black;
public InkInfo LightCyan;
public InkInfo LightMagenta;
public int MaintenanceTankStatus;
public int WasteInkTankStatus;
};
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct InkInfo {
public int InkStatus;
public double Remaining;
};
在 return 从服务中,所有字段都是空的。通常,显而易见的答案是数据协定不匹配(比如不同的命名空间)。但请注意,同一服务中的其他调用 returning 另一个非嵌套结构可以完美运行。命名空间和所有类似的东西都是正确的。
我尝试过的事情:
- 添加和删除
DataContract
和 DataMember
属性(两者都具有从程序集级别继承的命名空间和专门设置的名称,只是为了确定)。它们实际上不是必需的,推断的合同对我来说很好(通常的警告不适用,这是一个固定的打印机 SDK,服务的双方都在同一个应用程序中,在我的控制下)。
- 添加
KnownType(typeof(InkInfo))
。没有变化。
- 添加
[DataContract(IsReference = true)]
。作为一个结构,这会导致异常。
- 将结构更改为 类 并再次尝试以上所有操作。没有变化。
- 记录和跟踪通信显示数据是 return来自服务,只是客户端反序列化失败。
回顾一下:普通结构完美地工作。只有包含其他结构的结构才会失败。还有什么我忘了尝试的吗?
更新:这是服务的一个片段,另外调用return的BaseInfo
结构。它做到了 return,没问题。
[ServiceContract(Namespace = "http://schemas.example.com/2017/06/printer-service", Name = "printer")]
public interface IPrinterService {
[OperationContract]
int GetBaseInfo(uint printerID, out BaseInfo out_BaseInfo);
[OperationContract]
int GetInkInfo(uint printerID, out PrinterInfo out_PrinterInfo);
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class BaseInfo {
public string PrinterSerial;
public string Name;
public string ModelName;
};
通常情况下,除非事实证明这是不可避免的,否则没有明确的数据契约,只有推断的契约。数据契约命名空间在程序集级别提供(看起来是 SOAP 消息好吧):
[assembly: ContractNamespace("http://schemas.example.com/2017/06/printer-service", ClrNamespace = "MyApp.Printers")]
服务端刚好是用C++/CLI写的不过看起来差不多:
int GetBaseInfo(unsigned int printerID, [Out] BaseInfo% out_BaseInfo) {
...
Log::Debug(out_BaseInfo);
return result;
}
int GetInkInfo(unsigned int printerID, [Out] PrinterInfo% out_PrinterInfo) {
...
Log::Debug(out_PrinterInfo);
return result;
}
两个 Log::Debug()
调用都清楚地表明变量在离开函数之前已填充。
再一次,计算机是对的。 :-) 在某些结构中 是 的差异,一个很容易被忽略的差异:int
和 long
之间的差异。在 C# 世界中,它们分别是 32 位和 64 位,但在 C++/CLI 中(为了保持兼容性)它们都是 32 位的。我在某处定义了一个 'long',这意味着不同...
我需要 return 来自 WCF 服务的以下嵌套数据作为调用的 out
参数:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct PrinterInfo {
public InkInfo Cyan;
public InkInfo Magenta;
public InkInfo Yellow;
public InkInfo Black;
public InkInfo LightCyan;
public InkInfo LightMagenta;
public int MaintenanceTankStatus;
public int WasteInkTankStatus;
};
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct InkInfo {
public int InkStatus;
public double Remaining;
};
在 return 从服务中,所有字段都是空的。通常,显而易见的答案是数据协定不匹配(比如不同的命名空间)。但请注意,同一服务中的其他调用 returning 另一个非嵌套结构可以完美运行。命名空间和所有类似的东西都是正确的。
我尝试过的事情:
- 添加和删除
DataContract
和DataMember
属性(两者都具有从程序集级别继承的命名空间和专门设置的名称,只是为了确定)。它们实际上不是必需的,推断的合同对我来说很好(通常的警告不适用,这是一个固定的打印机 SDK,服务的双方都在同一个应用程序中,在我的控制下)。 - 添加
KnownType(typeof(InkInfo))
。没有变化。 - 添加
[DataContract(IsReference = true)]
。作为一个结构,这会导致异常。 - 将结构更改为 类 并再次尝试以上所有操作。没有变化。
- 记录和跟踪通信显示数据是 return来自服务,只是客户端反序列化失败。
回顾一下:普通结构完美地工作。只有包含其他结构的结构才会失败。还有什么我忘了尝试的吗?
更新:这是服务的一个片段,另外调用return的BaseInfo
结构。它做到了 return,没问题。
[ServiceContract(Namespace = "http://schemas.example.com/2017/06/printer-service", Name = "printer")]
public interface IPrinterService {
[OperationContract]
int GetBaseInfo(uint printerID, out BaseInfo out_BaseInfo);
[OperationContract]
int GetInkInfo(uint printerID, out PrinterInfo out_PrinterInfo);
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class BaseInfo {
public string PrinterSerial;
public string Name;
public string ModelName;
};
通常情况下,除非事实证明这是不可避免的,否则没有明确的数据契约,只有推断的契约。数据契约命名空间在程序集级别提供(看起来是 SOAP 消息好吧):
[assembly: ContractNamespace("http://schemas.example.com/2017/06/printer-service", ClrNamespace = "MyApp.Printers")]
服务端刚好是用C++/CLI写的不过看起来差不多:
int GetBaseInfo(unsigned int printerID, [Out] BaseInfo% out_BaseInfo) {
...
Log::Debug(out_BaseInfo);
return result;
}
int GetInkInfo(unsigned int printerID, [Out] PrinterInfo% out_PrinterInfo) {
...
Log::Debug(out_PrinterInfo);
return result;
}
两个 Log::Debug()
调用都清楚地表明变量在离开函数之前已填充。
再一次,计算机是对的。 :-) 在某些结构中 是 的差异,一个很容易被忽略的差异:int
和 long
之间的差异。在 C# 世界中,它们分别是 32 位和 64 位,但在 C++/CLI 中(为了保持兼容性)它们都是 32 位的。我在某处定义了一个 'long',这意味着不同...