Win8App 中给定数据的反序列化

Deserialization of given data in Win8App

我有一个 Win8App 和一个 WCF。 Win8App 进行不同的调用,WCF 提供 ListObservableCollections 的自定义 class,如下例中的 Person。我的问题是每个列表或集合到达我的 Win8App 时都是空的(不是空的)。我发现这是关于反序列化的,但现在该怎么办?

我用 ListArrayObservableCollectionIList 或只是一个对象写了一些测试代码,我从来没有得到异常但总是空的(不是空的) ) 集合或一个空的单个对象。是我的WCF/Win8App的反序列化问题还是配置问题?

WCF IService.cs:

[ServiceContract]
public interface IMyService
{       
    [OperationContract(Name = "GetPerson")]
    Person GetPerson();

    [OperationContract(Name = "GetPersons")]
    List<Person> GetPersons();

    [OperationContract(Name = "GetPersonArray")]
    Person[] GetPersonArray();

    [OperationContract(Name = "GetPersonList")]
    IList<Person> GetPersonList();

    [OperationContract(Name = "GetPersonCollection")]
    ObservableCollection<Person> GetPersonCollection();        
}

WCF.svc:

public Person GetPerson()
{
    return new Person() { Name = "asdf", IstZeit = new TimeSpan(10000000) };
}

public List<Person> GetPersons()
{
    List<Person> list = new List<Person>();
    for (int i = 0; i < 19; i++)
    {
        list.Add(new Person() { Name = "asdf", IstZeit = new TimeSpan(10000000) });

    }
    return list;
}


public ObservableCollection<Person> GetPersonCollection()
{
    ObservableCollection<Person> list = new ObservableCollection<Person>();
    for (int i = 0; i < 19; i++)
    {
        list.Add(new Person() { Name = "asdf", IstZeit = new TimeSpan(10000000) });

    }
    return list;
}

public Person[] GetPersonArray()
{
   List<Person> list = new List<Person>();
   for (int i = 0; i < 19; i++)
   {
       list.Add(new Person() { Name = "asdf", IstZeit = new TimeSpan(10000000) });

   }
   return list.ToArray();
}

public IList<Person> GetPersonList()
{
    List<Person> list = new List<Person>();
    for (int i = 0; i < 19; i++)
    {
        list.Add(new Person() { Name = "asdf", IstZeit = new TimeSpan(10000000) });

    }
    return list;
}

WCF - Class 人

[DataContract]
public class Person
{
    private string name;
    private string email;
    private TimeSpan istZeit;

    public Person()
    {

    }

    [DataMember]
    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    [DataMember]
    public TimeSpan IstZeit
    {
        get { return istZeit; }
        set { istZeit = value; }
    }

    [DataMember]
    public string Email
    {
        get { return email; }
        set { email = value; }
    }
}

现在我的Win8App.....

通过 ChannelFactory 设置 ServiceReference:

public static IMyService GetClientForService()
{
    EndpointAddress endpointAddress = new EndpointAddress("http://localhost:12345/Service1.svc");

    BasicHttpBinding basicHttpBinding = new BasicHttpBinding();     

    ChannelFactory<IMyService> channelFactory = channelFactory = new ChannelFactory<IMyService>(basicHttpBinding, endpointAddress);
    IMyService client = channelFactory.CreateChannel();            

    return client;
}

在我的 Win8App 中,我为 IMyServicePerson 实现了与 WCF 中相同的代码。

此方法正在调用 WCF:

private void CheckWCFMethods()
{
    IMyService client = ServiceBinding.GetClientForService();

    var p = client.GetPerson();
    IList<Person> iList = client.GetPersonList();
    ObservableCollection<Person> collection = client.GetPersonCollection();
    Person[] array = client.GetPersonArray();
    List<Person> list = client.GetPersons();

    #if(DEBUG)
    Debug.WriteLine(string.Format("SinglePersonName:{0}\niList.Count:{1}\nCollection.Count:{2}\nArray.Length:{3}\nList.Count:{4}",string.IsNullOrEmpty(p.Name) ? "empty" : p.Name, iList.Count, collection.Count, array.Length, list.Count));
    Debug.WriteLine("DONE");
    #endif
}

调试结果总是:

**DEBUGRESULT**
SinglePersonName:empty
IList.Count:0
Collection.Count:0
Array.Length:0
List.Count:0
DONE

但是当我通过 WCF-Testclient 直接执行 WCF 时,我得到:

SinglePersonName: asdf
IList.Count:19
Collection.Count:19
Array.Length:19
List.Count:19


我尝试设置 [KnownType][ServiceKnownType](服务器端和客户端),但没有任何改变。我以前只写过 2 或 3 个 WCF,但从来没有处理过反序列化问题,因为当我通过 Visual Studio 设置 ServiceReference 时,集合类型和字典集合类型是自动设置的(或通过简单的点击)。所以我是 ChannelFactory 的新手,也是服务器端和客户端的序列化编码的新手。

我应该如何反序列化 Win8App 中的数据?


如果您需要任何进一步的信息,请告诉我!


** 编辑 **

所以我尝试在客户端为 class 人设置命名空间(class Person 在我的 TestWCF 中名为 "DataContracts" 的文件夹中):

[DataContract(Namespace = "http://localhost:12345/DataContracts")]
public class Person{}

但结果仍然是这样的:

**DEBUGRESULT**
SinglePersonName:empty
IList.Count:0
Collection.Count:0
Array.Length:0
List.Count:0
DONE

** 编辑 **

所以我用我的 windows 8.1 测试应用程序尝试了一些事情,这让我感到困惑,一个正常的 visual studio 服务引用运行良好,而我的 channelfactory "reference" 什么都不做- 无法弄清楚它有什么问题:

我真的很困惑,如果你想自己尝试,你可以在这里下载这个示例 wcf 和 w8.1app(我的 googledrive): Testfiles

您只需在 win8.1 应用程序中设置端点地址的 uri 并启动 wcf(或在 iis 上发布)。

关于这个主题的任何进一步信息?

如果您按原样复制/粘贴数据/服务合同,那么您可能会遇到 XML 命名空间不匹配的情况。当 XML 通过 WCF 请求/响应中的线路时,其元素位于某些 XML 命名空间内。当您定义 [DataContract][ServiceContract] 而未明确指定要使用哪个 XML 命名空间时,WCF 将默认使用从 class 本身的命名空间派生的命名空间(即,它的 CLR 命名空间)。

如果您有两个 class,一个在客户端,一个在服务器上用于数据协定,但它们位于不同的 CLR 命名空间中(例如,MyApp.Service.PersonMyApp.Client.Person),那么 WCF 使用的 XML 对应于那些 classes 是不同的。

如果确实如此,请尝试在您的数据协定中明确定义命名空间,这样这种不匹配就不会再发生了:

[DataContract(Namespace = "http://my.company.com/contracts")]
public class Person
{
    private string name;
    private string email;
    private TimeSpan istZeit;

    public Person()
    {

    }

    [DataMember]
    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    [DataMember]
    public TimeSpan IstZeit
    {
        get { return istZeit; }
        set { istZeit = value; }
    }

    [DataMember]
    public string Email
    {
        get { return email; }
        set { email = value; }
    }
}

另一种选择是在您的客户端项目上使用诸如 Visual Studio 上的 "Add Service Reference" 之类的工具,将其指向服务元数据(如果已启用)。该工具将使用适当的命名空间声明创建要在客户端中使用的 classes。

你应该用 [ServiceContract] 属性标记一个界面

[ServiceContract]
public interface IMyService

今天我 运行 遇到了一个问题,即序列化程序在尝试反序列化时间跨度时卡住了。在我的例子中,从要序列化的对象中删除时间跨度解决了这个问题。我能够用整数(秒数)替换时间跨度,不确定这是否适合你,但可能需要检查一下。