Como posso adicionar uma restrição de tipo para incluir qualquer coisa serializável em um método genérico?

StackOverflow https://stackoverflow.com/questions/945495

Pergunta

Meu método genérico precisa serializar o objeto passado para ele, porém apenas insistir que ele implemente ISerializable não parece funcionar.Por exemplo, tenho uma estrutura retornada de um serviço da Web (marcado com SerializableAttribute) que serializa para xml perfeitamente, mas, como esperado, o compilador C# reclama.

Existe uma maneira de verificar se o objeto é serializável antes de tentar serializá-lo ou, melhor ainda, uma maneira de usar o where palavra-chave para verificar se o objeto é adequado?

Aqui está meu método completo:

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

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

Se isso não for possível, qual é a melhor maneira de verificar se um objeto é serializável em tempo de execução?

Foi útil?

Solução

Você não pode fazer isso totalmente por meio de restrições genéricas, mas pode fazer algumas coisas para ajudar:

1) Coloque o novo() restrição ao tipo genérico (para permitir a capacidade de desserializar e garantir que o XMLSerializer não reclame da falta de ctor padrão):

where T : new()

2) Na primeira linha do seu método, lidando com a serialização (ou construtor ou em qualquer outro lugar que você não precise repeti -lo repetidamente), você pode executar esta verificação:

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

Obviamente, ainda existe a possibilidade de exceções de tempo de execução ao tentar serializar um tipo, mas isso abrangerá os problemas mais óbvios.

Outras dicas

Escrevi um longo artigo no blog sobre esse assunto que pode ser útil para você.Ele se aplica principalmente à serialização binária, mas os conceitos são aplicáveis ​​a quase todos os formatos de serialização.

O resumo é

  • Não há como adicionar uma restrição genérica confiável
  • A única maneira de verificar se um objeto era serializable é serializá-lo e ver se a operação foi bem-sucedida

A única maneira de saber se um objeto é serializável é tentar serializar -o.

De fato, você estava perguntando como saber se um tipo "é serializável", mas a pergunta real será em relação aos objetos. Algumas instâncias de um tipo podem não ser serializáveis, mesmo que o tipo esteja marcado [serializável]. Por exemplo, e se a instância contiver referências circulares?

Ao invés de

XmlSerializer xmlSerializer = new XMLSerializer (typeof (t));

tentar

XmlSerializer xmlSerializer = new XMLSerializer (message.getType ());

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top