具有RegEx列表的WCF DataContract将无法正确序列化

时间:2011-10-26 21:39:16

标签: regex wcf serialization datacontract datamember

我有一个看起来像这样的课程:

[DataContract]
public class InboundMailbox
{
    public const char EmailSeparator = ';';

    [DataMember]
    public string POP3Host { get; set; }

    [DataMember]
    public string EmailId { get; set; }

    [DataMember]
    public string WebServiceURL { get; set; }

    [DataMember]
    public List<Regex> Allowed { get; set; }

    [DataMember]
    public List<Regex> Disallowed { get; set; }
}

如果AllowedDisallowed为空,那么它在我的WCF服务中进行了很好的序列化。只要其中一个列表包含一个值,我就会在CommunicationException中得到它:

  

套接字连接已中止。这可能是由错误引起的   处理您的消息或超过接收超时   远程主机或底层网络资源问题。本地套接字   超时为'00:00:29.9899990'。

为什么让我很难将这两个属性序列化?提前谢谢。

1 个答案:

答案 0 :(得分:3)

Regex类实现ISerializable接口,这意味着它被序列化为属性包(字符串/对象的字典)。查看Reflector中ISerializable.GetObjectData类的Regex实现,它表明它序列化了模式(字符串)和选项(类型RegexOptions)。由于类型为ISerializable,因此WCF不会知道关于RegexOptions,因此无法序列化此类型。

一个简单的解决方案是简单地“告诉”WCF这是一个已知类型,因此序列化将起作用(一个容易的地方来声明它正在使用[KnownType]属性InboundMailbox类(见下文)。另一种选择是将数据成员作为正则表达式而不是Regex本身(也可能是选项)。

public class StackOverflow_7909261
{
    [DataContract]
    [KnownType(typeof(RegexOptions))]
    public class InboundMailbox
    {
        public const char EmailSeparator = ';';

        [DataMember]
        public string POP3Host { get; set; }

        [DataMember]
        public string EmailId { get; set; }

        [DataMember]
        public string WebServiceURL { get; set; }

        [DataMember]
        public List<Regex> Allowed { get; set; }

        [DataMember]
        public List<Regex> Disallowed { get; set; }
    }

    public static void Test()
    {
        MemoryStream ms = new MemoryStream();
        InboundMailbox obj = new InboundMailbox
        {
            POP3Host = "popHost",
            EmailId = "email",
            WebServiceURL = "http://web.service",
            Allowed = new List<Regex>
            {
                new Regex("abcdef", RegexOptions.IgnoreCase),
            },
            Disallowed = null,
        };
        DataContractSerializer dcs = new DataContractSerializer(typeof(InboundMailbox));
        try
        {
            dcs.WriteObject(ms, obj);
            Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }
}

顺便说一句,如果你在服务器端启用了跟踪,你会发现错误;它会有一个例外,表示类型RegexOptions不是预期的。