#regex #wcf #serialization #datacontract #datamember
#регулярное выражение #wcf #сериализация #datacontract #элемент данных
Вопрос:
У меня есть класс, который выглядит примерно так:
[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. Насколько велик список регулярных выражений, которые вы отправляете по проводам?
2. Если я помещу одно регулярное выражение в один из списков, я получу исключение. И сами регулярные выражения не такие длинные, вероятно, <20 символов.
Ответ №1:
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
не ожидался.
Комментарии:
1. Ты когда-нибудь знал, что ты мой герой и все, чем я хотел бы быть? Я могу летать выше орла, потому что ты ветер под моими крыльями.