Как я могу добавить ограничение типа, чтобы включить все сериализуемые в универсальный метод? - PullRequest
40 голосов
/ 03 июня 2009

Мой универсальный метод должен сериализовать переданный ему объект, однако просто настаивать на том, что он реализует ISerializable, похоже, не работает. Например, у меня есть структура, возвращенная из веб-службы (помечена SerializableAttribute), которая отлично сериализуется в xml, но, как и ожидалось, компилятор C # жалуется.

Есть ли способ проверить сериализуемость объекта перед попыткой его сериализации или, что еще лучше, использовать ключевое слово where для проверки пригодности объекта?

Вот мой полный метод:

public static void Push<T>(string url, T message)
        where T : ISerializable
{
    string xml = SerializeMessage(message);

    // Send the message to Amazon SQS
    SendMessageRequest sendReq = new SendMessageRequest { QueueUrl = url, MessageBody = xml };
    AmazonSQSClient client = new AmazonSQSClient(S3User, S3Pass);
    client.SendMessage(sendReq);
}

И SerializeMessage:

private static string SerializeMessage<T>(T message)
{
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
    using (StringWriter stringWriter = new StringWriter())
    {
        xmlSerializer.Serialize(stringWriter, message);
        return stringWriter.ToString();
    }
}

Если это невозможно, каков наилучший способ проверки сериализации объекта во время выполнения?

Ответы [ 4 ]

37 голосов
/ 03 июня 2009

Вы не можете сделать это полностью через общие ограничения, но вы можете сделать пару вещей, чтобы помочь:

1) Установите ограничение new () на универсальный тип (чтобы обеспечить возможность десериализации и убедиться, что XmlSerializer не жалуется на отсутствие ctor по умолчанию):

where T : new()

2) В первой строке вашего метода, обрабатывающего сериализацию (или конструктор или где-либо еще, вам не нужно повторять это снова и снова), вы можете выполнить эту проверку:

if( !typeof(T).IsSerializable && !(typeof(ISerializable).IsAssignableFrom(typeof(T)) ) )
    throw new InvalidOperationException("A serializable Type is required");

Конечно, по-прежнему существует вероятность исключений во время выполнения при попытке сериализации типа, но это покроет наиболее очевидные проблемы.

8 голосов
/ 03 июня 2009

Я написал длинную статью в блоге на эту тему, которая может оказаться вам полезной. В основном речь идет о двоичной сериализации, но эти концепции применимы практически к любому формату сериализации.

Длинная и короткая это

  • Нет способа добавить надежное общее ограничение
  • Единственный способ проверить и посмотреть, был ли объект сериализуемый сериализованным, - это сериализовать его и посмотреть, успешно ли выполнена операция
3 голосов
/ 03 июня 2009

Единственный способ узнать, сериализуем ли объект, - это попытаться его сериализовать.

На самом деле, вы спрашивали, как определить, является ли тип «сериализуемым», но реальный вопрос будет касаться объектов. Некоторые экземпляры типа могут не быть сериализуемыми, даже если тип помечен как [Serializable]. Например, что если экземпляр содержит циклические ссылки?

0 голосов
/ 03 июня 2009

вместо

XmlSerializer xmlSerializer = new XmlSerializer (typeof (T));

попробуй

XmlSerializer xmlSerializer = new XmlSerializer (message.GetType ());

...