【问题标题】:WCF tries to serialize members that are not attributed with [DataMember]WCF 尝试序列化不属于 [DataMember] 的成员
【发布时间】:2016-07-04 09:32:15
【问题描述】:

给定以下 DataContract:

[DataContract]
public class GetGameSessionHistory : ValueBaseCasinoIT
{
    [DataMember]
    public GameSession[] GameSessions => GameSessionsValue.ToArray<GameSession>();

    public IEnumerable<GameSession> GameSessionsValue { get; set; }
}

由于 IEnumerable 接口,我仍然收到 GetGameSessionHistory 不可序列化的错误消息。

System.NotSupportedException: Cannot serialize member GetGameSessionHistory.GameSessionsValue of type System.Collections.Generic.IEnumerable`1[[GameSession, Common, Version=3.45.0.11, Culture=neutral, PublicKeyToken=null]] because it is an interface.

我还尝试了删除整个 [DataContract] 属性的方法,并专门使用 [IgnoreDataMember] 忽略受影响的成员。但不幸的是,这会导致相同的结果。

更新 1

给定代码中的 Lambda 表达式只是我计划做的一个步骤。使用以下 DataContract 时问题仍然存在:

[DataContract]
public class GetGameSessionHistory : ValueBaseCasinoIT
{
    [DataMember]
    public GameSession[] GameSessions { get; set; }

    public IEnumerable<GameSession> GameSessionsValue { get; set; }
}

删除 IEnumerable 时,消息消失。所以问题不可能来自 GameSession 类型。

目前我正在使用 XmlSerializer

数据用于以下服务:

IAdapterService:

[ServiceContract, XmlSerializerFormat(Style = OperationFormatStyle.Rpc, Use = OperationFormatUse.Encoded), DispatchByBodyBehavior]
public interface IAdapterService
{
    [OperationContract(Name = "GetGameSessionHistoryRequest", Action = ""), DispatchBodyElement("GetGameSessionHistoryRequest", "...")]
    GetGameSessionHistory GetGameSessionHistory(AuthenticationToken authenticationToken, string playerId, DateTime fromDate, DateTime toDate);
}

适配器服务:

[SoapDocumentService(SoapBindingUse.Literal, RoutingStyle = SoapServiceRoutingStyle.RequestElement)]
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
public class AdapterService : IAdapterService
{
    public GetGameSessionHistory GetGameSessionHistory(AuthenticationToken authenticationToken, string playerId, DateTime fromDate, DateTime toDate)
    { ... }
}

Web.config:

<basicHttpBinding>
    <binding name="SoapBinding">
        <security mode="None"/>
        <readerQuotas maxDepth="4000" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="32768"/>
    </binding>
</basicHttpBinding>

<service name="...svc.AdapterService" behaviorConfiguration="svcBehavior" >
    <endpoint binding="basicHttpBinding" bindingConfiguration="SoapBinding" contract="...IAdapterService" name="AdapterSoapBinding" behaviorConfiguration="withMessageInspector"/>
</service>

还有什么可能导致这个问题?

【问题讨论】:

  • 好吧,除此之外:它无法反序列化 GameSessions
  • 您能否确切地确认 WCF 配置为使用哪个序列化程序?有DataContractSerializerNetDataContractSerializer,可以通过配置选择。 (编辑:虽然我在答案的代码中尝试了NetDataContractSerializer,但它仍然运行良好)

标签: c# wcf datacontract datamember


【解决方案1】:

如果我尝试您的代码,序列化工作正常;反序列化失败:

System.Runtime.Serialization.SerializationException:“GameSession[]”类型的 get-only 集合返回空值。如果实例为空,则输入流包含无法添加的集合项。考虑在 getter 中初始化集合。

这是我所期望的,因为它无法为GameSessions 赋值。如果我添加 set... 一切正常。这是完整的工作代码:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;

class Program
{
    static void Main()
    {
        var ser = new DataContractSerializer(typeof(GetGameSessionHistory));
        using (var ms = new MemoryStream())
        {
            var orig = new GetGameSessionHistory { GameSessionsValue =
                new List<GameSession>() { new GameSession { } } };
            ser.WriteObject(ms, orig);
            ms.Position = 0;
            var clone = (GetGameSessionHistory)ser.ReadObject(ms);
            Console.WriteLine(clone?.GameSessionsValue.Count()); // prints 1
        }
    }

}
[DataContract]
public class GetGameSessionHistory : ValueBaseCasinoIT
{
    [DataMember]
    public GameSession[] GameSessions
    {
        get { return GameSessionsValue?.ToArray(); }
        set { GameSessionsValue = value; }
    }
    //[DataMember] // original version; fails with The get-only collection of type
                   // 'GameSession[]' returned a null value.
    //public GameSession[] GameSessions => GameSessionsValue?.ToArray<GameSession>();

    public IEnumerable<GameSession> GameSessionsValue { get; set; }
}

[DataContract]
public class ValueBaseCasinoIT
{
}

[DataContract]
public class GameSession
{
}

我认为您可能需要添加更多信息来帮助我们确定问题,因为...它基本上可以工作。

【讨论】:

  • 感谢您的提示,我稍后会考虑。请注意我的新更新。希望现在有足够的信息来解决根本问题。
【解决方案2】:

发现问题: 我使用的是 XmlSerializer(IAdapterService 使用 [XmlSerializerFormat]),它会导致所有公共属性都被序列化。

DataContractSerializer (XmlObjectSerializer) 会考虑序列化过程的 [DataMember] 属性,而 XmlSerializer 只是忽略它们。

问题仍然存在,为什么 [XmlIgnore] 属性不能正常工作。

【讨论】:

    猜你喜欢
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-20
    • 1970-01-01
    • 1970-01-01
    • 2012-07-03
    相关资源
    最近更新 更多