I have a class that looks something like this:

[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; }
}

If Allowed and Disallowed are empty then it serializes just fine across my WCF service. As soon as one of those lists contains a value, I get this in a CommunicationException:

The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:00:29.9899990'.

Why is it giving me a hard time about serializing those two properties? Thanks in advance.

有帮助吗?

解决方案

The Regex class implements the ISerializable interface, which means that it's serialized as a property bag (dictionary of string/object). Looking at the implementation of ISerializable.GetObjectData for the Regex class in Reflector, it shows that it serializes both the pattern (string) and the options (of type RegexOptions). Since the type is ISerializable, WCF doesn't know about RegexOptions, so it will fail to serialize this type.

One simple solution is to simply "tell" WCF that this is a known type, so the serialization will work (an easy place to declare it is using the [KnownType] attribute in the InboundMailbox class (see below). Another option would be to have the data member as the regex pattern instead of the Regex itself (and possibly the options as well).

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);
        }
    }
}

BTW, you'd find out the error if you had enabled tracing on the server side; it would have an exception saying that the type RegexOptions wasn't expected.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top