WCF DataContract со списком RegEx не будет правильно сериализован - PullRequest
3 голосов
/ 27 октября 2011

У меня есть класс, который выглядит примерно так:

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

Если Allowed и Disallowed пустые, то они отлично сериализуются в моей службе WCF. Как только один из этих списков содержит значение, я получаю это в CommunicationException:

Соединение с сокетом было прервано. Это может быть вызвано ошибкой обработка вашего сообщения или превышение времени ожидания удаленный хост или проблема с сетевым ресурсом. Локальный сокет тайм-аут был '00: 00: 29.9899990 '.

Почему мне так сложно сериализовать эти два свойства? Заранее спасибо.

1 Ответ

3 голосов
/ 27 октября 2011

Класс Regex реализует интерфейс ISerializable, что означает, что он сериализован как мешок свойств (словарь строки / объекта).Рассматривая реализацию ISerializable.GetObjectData для класса Regex в Reflector, он показывает, что он сериализует как шаблон (строку), так и параметры (типа 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 не ожидался.

...