如何解决<T>的IPC/WCF通过列表
我认为这个问题已经被问了很多时间,但即使我阅读了 MSFT 的文章和 StackOverflow 上的一些主题,我似乎也无法解决这个问题。
我对 IPC/WCF 真的很陌生,但我开始在我的 WPF 应用程序中使用它,因为它很简单。现在我的情况似乎无法开始工作。
问题很简单,我想将 List of <T>
传递给服务器(这也是一个 WPF 应用程序)。我可以看到它是使用 fiddler 发送的,但在序列化时没有任何反应。这是因为根据我的理解,它已转换为数组。所以我将它调整为一个数组,但仍然没有值。
在客户端和服务器之间共享(复制和粘贴)DataContract:
<DataContract>
<AttributeUsage(AttributeTargets.Class)>
<KNownType(GetType(List(Of Integer)))>
Public Class UnauthorizedFolder
<DataMember>
Public Property RootFolderId As Integer
<DataMember>
Public Property ChildIds As New List(Of Integer)
Public Overrides Function ToString() As String
Return $"{RootFolderId} = [{String.Join(",",ChildIds)}]"
End Function
End Class
客户端和服务器之间共享(复制和粘贴)合同
<ServiceContract()>
Public Interface MyRemoteControls
<OperationContract()> Sub UserAccessGranted(UserName As String,lstUnauthorisedFolders As List(Of UnauthorizedFolder))
<OperationContract()> Sub UserAccessRevoked()
End Interface
设置服务器端:
_ServiceHost = New ServiceHost(GetType(RemoteControl),New Uri("http://127.0.0.1:8080/MyService"))
_ServiceHost.AddServiceEndpoint(GetType(MyRemoteControls),New BasicHttpBinding(),"MyService")
_ServiceHost.open()
然后是服务器远程类:
Class RemoteControl
Implements MyRemoteControls
Dim strCurrentUserName As String
Public Sub UserAccesGranted(UserName As String,lstUnauthorisedFolders As List(Of UnauthorizedFolder)) Implements MyRemoteControls.UserAccessGranted
strCurrentUserName = UserName
If lstUnauthorisedFolders Is nothing OrElse lstUnauthorisedFolders.Count <= 0 Then
Debug.Print($"{Now.ToString("hh:mm:ss")} - UserAccesGranted: [{strCurrentUserName}] - All Folders{vbCrLf}")
Else
Debug.Print($"{Now.ToString("hh:mm:ss")} - UserAccesGranted: [{strCurrentUserName}] {lstUnauthorisedFolders .Count}{vbCrLf}")
End If
End Sub
Public Sub UserAccesRevoked() Implements MyRemoteControls.UserAccessRevoked
Debug.Print($"{Now.ToString("hh:mm:ss")} - UserAccesRevoked: [{strCurrentUserName}]{vbCrLf}")
End Sub
End Class
现在从客户端我可以看到 XML 被发送到服务器
<s:Envelope
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<UserAccessGranted
xmlns="http://tempuri.org/">
<UserName>User 1(1)</UserName>
<lstUnauthorisedFolders
xmlns:a="http://schemas.datacontract.org/2004/07/MyApp"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:UnauthorizedFolder>
<a:ChildIds
xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<b:int>1</b:int>
<b:int>2</b:int>
<b:int>4</b:int>
<b:int>5</b:int>
<b:int>8</b:int>
</a:ChildIds>
<a:RootFolderId>3</a:RootFolderId>
</a:UnauthorizedFolder>
</lstUnauthorisedFolders>
</UserAccessGranted>
</s:Body>
</s:Envelope>
因此客户端以正确的方式发送所有内容(使用 ChannelFactory
),但似乎在服务器上进行序列化时 lstUnauthorisedFolders
未序列化。
我看到一些答案,描述我必须将 ServiceReference 中的类型从 Array
调整为 Generic.List
才能解决此问题,但在 WPF 而非 ASP.NET 中的服务器应用程序中,我没有这样的设定?
我测试过并有效的解决方法是使用 Newtonsoft.JSON
将 List of <T>
作为字符串传递,然后在服务器端将其序列化回 List of <T>
但我发现这是一个丑陋的解决方法因为 List of <T>
也支持 XML。
希望有人能指出我正确的方向,谢谢!
解决方法
尝试以下操作:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication184
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
string xml = File.ReadAllText(FILENAME);
StringReader sReader = new StringReader(xml);
XmlReader xReader = XmlReader.Create(sReader);
XmlSerializer serializer = new XmlSerializer(typeof(Envelope));
Envelope envelope = (Envelope)serializer.Deserialize(xReader);
}
}
[XmlRoot(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
{
public Body Body { get; set; }
}
public class Body
{
[XmlElement(Namespace = "http://tempuri.org/")]
public UserAccessGranted UserAccessGranted { get; set; }
}
public class UserAccessGranted
{
public string UserName { get; set; }
public lstUnauthorisedFolders lstUnauthorisedFolders { get; set; }
}
public class lstUnauthorisedFolders
{
[XmlElement(Namespace = "http://schemas.datacontract.org/2004/07/MyApp")]
public UnauthorizedFolder UnauthorizedFolder { get; set; }
}
public class UnauthorizedFolder
{
[XmlElement(Namespace = "http://schemas.datacontract.org/2004/07/MyApp")]
public ChildIds ChildIds { get; set; }
[XmlElement(Namespace = "http://schemas.datacontract.org/2004/07/MyApp")]
public int RootFolderId { get; set; }
}
public class ChildIds
{
[XmlElement(ElementName = "int",Namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays")]
public List<int> numbers { get; set; }
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。