微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

<T>的IPC/WCF通过列表

如何解决<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.JSONList 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 举报,一经查实,本站将立刻删除。