Converta um objeto em uma string XML

87

Eu tenho uma classe chamada WebserviceTypeque obtive da ferramenta xsd.exe de um arquivo XSD.

Agora eu quero desserializar uma instância de um WebServiceTypeobjeto para uma string. Como posso fazer isso?

O MethodCheckTypeobjeto tem como parâmetros um WebServiceTypearray.

Minha primeira tentativa foi como se eu o serializasse: com ae XmlSerializera StringWriter(enquanto serializava, usei a StringReader).

Este é o método em que serializo o WebServiceTypeobjeto:

XmlSerializer serializer = new XmlSerializer(typeof(MethodCheckType));
        MethodCheckType output = null;
        StringReader reader = null;

        // catch global exception, logg it and throw it
        try
        {
            reader = new StringReader(path);
            output = (MethodCheckType)serializer.Deserialize(reader);
        }
        catch (Exception)
        {
            throw;
        }
        finally
        {
            reader.Dispose();
        }

        return output.WebService;

Editar:

Talvez eu pudesse dizer em outras palavras: eu tenho uma instância desse MethodCheckTypeobjeto e, por outro lado, tenho o documento XML a partir do qual serializei esse objeto. Agora, quero converter essa instância em um documento XML na forma de uma string. Depois disso, tenho que verificar se as duas strings (de documentos XML) são iguais. Tenho que fazer isso, porque faço testes de unidade do primeiro método em que li um documento XML em um StringReadere o serializo em um MethodCheckTypeobjeto.

FluepkeSchaeng
fonte
2
Que erro você obteve? E você pode estar confundindo os termos: serialização (no mundo XML) é a conversão de um objeto em XML ; a desserialização é a conversão de XML em um objeto . Você quer desserializar um objeto de uma string XML?
carlosfigueira

Respostas:

186

Aqui estão os métodos de conversão para as duas maneiras. this = instância de sua classe

public string ToXML()
    {
        using(var stringwriter = new System.IO.StringWriter())
        { 
            var serializer = new XmlSerializer(this.GetType());
            serializer.Serialize(stringwriter, this);
            return stringwriter.ToString();
        }
    }

 public static YourClass LoadFromXMLString(string xmlText)
    {
        using(var stringReader = new System.IO.StringReader(xmlText))
        {
            var serializer = new XmlSerializer(typeof(YourClass ));
            return serializer.Deserialize(stringReader) as YourClass ;
        }
    }
Tomas Grosup
fonte
13
Você deve usar um usingpadrão ou Disposemétodo de chamada para a liberação correta de recursos.
Ivan Kochurkin
Você deve ter certeza de que o código não gerenciado não é usado em todas as versões do CLR.
AlphaOmega
3
Por quê? Porque você deve descartar tudo que consome muitos recursos (não gerenciado e gerenciado ). Só porque o coletor de lixo vai limpar para você (eventualmente) não significa que você deve tornar o trabalho excessivamente difícil. Limpe conforme você avança e seu código será mais eficiente. Mais informações sobre por que o descarte explícito é uma boa ideia aqui
Liam
1
apenas para maior clareza. vocês estão falando sobre descartar StringWriter e StringReader (já que XmlSerializer não tem um método Dispose)
simbionte
o fim da função não libera recursos com a mesma eficiência using? @KvanTTT?
Mark Entingh
76

Sei que esta é uma postagem muito antiga, mas depois de olhar a resposta de LB, pensei em como poderia melhorar a resposta aceita e torná-la genérica para meu próprio aplicativo. Aqui está o que eu inventei:

public static string Serialize<T>(T dataToSerialize)
{
    try
    {
        var stringwriter = new System.IO.StringWriter();
        var serializer = new XmlSerializer(typeof(T));
        serializer.Serialize(stringwriter, dataToSerialize);
        return stringwriter.ToString();
    }
    catch
    {
        throw;
    }
}

public static T Deserialize<T>(string xmlText)
{
    try
    {
        var stringReader = new System.IO.StringReader(xmlText);
        var serializer = new XmlSerializer(typeof(T));
        return (T)serializer.Deserialize(stringReader);
    }
    catch
    {
        throw;
    }
}

Esses métodos agora podem ser colocados em uma classe auxiliar estática, o que significa que não há duplicação de código para cada classe que precisa ser serializada.

William Smith
fonte
10
No método "Serialize", use dataToSerialize.GetType () em vez de typeof (T). À primeira vista, parece seguro usar T como o tipo, mas se o objeto "dataToSerialize" tiver sido convertido para um tipo pai (ChildClass convertido para BaseClass), ocorrerá um erro. E verifique se há null primeiro, é claro.
Paul Easter,
1
Qual é o ponto de travar apenas para relançar sem fazer mais nada?
esmagamento de
Ótima pergunta; Eu não estava tentando desenvolver uma imagem completa aqui, apenas a estrutura para a funcionalidade e, definitivamente, não queria dar um exemplo que engula a exceção. Parecia uma boa alternativa genérica na época. Sinta-se à vontade para sugerir melhorias!
William Smith
Boa solução reutilizável.
Nitesh Saxena
21
    public static string Serialize(object dataToSerialize)
    {
        if(dataToSerialize==null) return null;

        using (StringWriter stringwriter = new System.IO.StringWriter())
        {
            var serializer = new XmlSerializer(dataToSerialize.GetType());
            serializer.Serialize(stringwriter, dataToSerialize);
            return stringwriter.ToString();
        }
    }

    public static T Deserialize<T>(string xmlText)
    {
        if(String.IsNullOrWhiteSpace(xmlText)) return default(T);

        using (StringReader stringReader = new System.IO.StringReader(xmlText))
        {
            var serializer = new XmlSerializer(typeof(T));
            return (T)serializer.Deserialize(stringReader);
        }
    }
Elanchezhian Narayanasamy
fonte
1
Serialize precisa de genéricos. O objeto é o suficiente. if (dataToSerialize == null) retorna null; ... var serializer = new XmlSerializer (dataToSerialize.GetType ()); ...
AlphaOmega
0

Esta é a minha solução, para qualquer objeto de lista, você pode usar este código para converter para layout xml. KeyFather é sua tag principal e KeySon é onde começa seu Forech.

public string BuildXml<T>(ICollection<T> anyObject, string keyFather, string keySon)
    {
        var settings = new XmlWriterSettings
        {
            Indent = true
        };
        PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
        StringBuilder builder = new StringBuilder();
        using (XmlWriter writer = XmlWriter.Create(builder, settings))
        {
            writer.WriteStartDocument();
            writer.WriteStartElement(keyFather);
            foreach (var objeto in anyObject)
            {
                writer.WriteStartElement(keySon);
                foreach (PropertyDescriptor item in props)
                {
                    writer.WriteStartElement(item.DisplayName);
                    writer.WriteString(props[item.DisplayName].GetValue(objeto).ToString());
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
            }
            writer.WriteFullEndElement();
            writer.WriteEndDocument();
            writer.Flush();
            return builder.ToString();
        }
    }
Fred Peixoto
fonte