Usa XmlDeserializer nel metodo di fabbrica?

0

Ho la seguente classe che rappresenta una configurazione XML memorizzata nel DB:

using System.IO;
using System.Xml;
using System.Xml.Serialization;

[XmlRoot("ModalConfiguration")]
public class XmlConfiguration
{
    [XmlElement("Field1")]
    public XmlConfigurationField Field1 { get; set; }
    [XmlElement("Field2")]
    public XmlConfigurationField Field2 { get; set; }
    [XmlElement("Field3")]
    public XmlConfigurationField Field3 { get; set; }

    public static XmlConfiguration GetFromXmlString(string xmlString)
    {
        using (TextReader reader = new StringReader(xmlString))
        {
            var xmlSerializer = new XmlSerializer(typeof(XmlConfiguration));
            return xmlSerializer.Deserialize(reader) as XmlConfiguration;
        }
    }

    public string ToXmlString()
    {
        var sw = new StringWriter();
        using (XmlWriter writer = XmlWriter.Create(sw))
        {
            var xmlSerializer = new XmlSerializer(typeof(XmlConfiguration));
            xmlSerializer.Serialize(writer, this);
            return sw.ToString();
        }
    }
}

Un collega mi ha detto che questa non è una buona pratica, specialmente il metodo statico di fabbrica, dal momento che il tipo non dovrebbe essere consapevole di come è stato costruito. Invece, mi ha suggerito di creare una classe separata con due metodi, uno che accetta una stringa XML restituisce un oggetto XmlConfiguration e uno che accetta un oggetto e restituisce una stringa; e lasciare questa classe come un semplice DTO.

Tuttavia, non vedo alcun problema nell'oggetto stesso che conosce gli interni della sua costruzione (per deserializzazione), e al contrario penso che otteniamo un buon incapsulamento con il mio approccio.

Che cosa pensi, puoi segnalare alcuni vantaggi o svantaggi dei due approcci?

    
posta Gua-naiko-che 10.11.2016 - 15:57
fonte

2 risposte

1

L'approccio alla serializzazione e alla deserializzazione dipende dall'ambiente di distribuzione e dal contesto. Più specificamente, quanto è critico questo componente nello schema generale delle cose influirà sul modo in cui si affronta l'affidabilità, la sicurezza, la testabilità e altre ... leità.

La serializzazione ingenua fa presupporre che    - la versione di ciò che hai esportato è la stessa di quello che importi.    - nessun danneggiamento si verifica nel formato di esportazione    - nessun utente malintenzionato sta prendendo di mira il tuo DTO. Se nessuno di questi è un problema per te, allora il tuo approccio potrebbe funzionare.

Altri approcci di serializzazione potrebbero essere utilizzati in futuro: Java, JSON, diverse versioni di XML, per esempio, e alcuni di essi potrebbero verificarsi nella stessa distribuzione. Separando la tua fabbrica dai dati sottostanti, corri meno possibilità di travolgere i dati sottostanti con la logica di importazione / esportazione non banale.

Piccoli progetti con piccoli requisiti possono riunire questi aspetti nella stessa classe.

    
risposta data 10.11.2016 - 16:27
fonte
1

Il tuo design è OK se questa è l'unica classe che viene serializzata. Ma ...

Ogni classe che è scritta sotto questo progetto avrà bisogno di GetFromXmlString e ToXmlString di implementazione poiché è specifica per la classe.

Dovrebbe essere separato in modo che la serializzazione possa gestire qualsiasi classe che abbia markup di serializzazione. Ecco un esempio di una serializzazione generica per qualsiasi stringa su oggetto:

        public static T XmlStringToObject<T>(this string xml, string nameSpace=null)
        {
            if (string.IsNullOrWhiteSpace(xml)) return default(T);

            var serializer = nameSpace == null ? new XmlSerializer(typeof (T)) : new XmlSerializer(typeof (T), nameSpace);

            if (!_diagnosticsOn) return (T) serializer.Deserialize(new StringReader(xml));

            serializer.UnknownNode += serializer_UnknownNode;
            serializer.UnknownElement += serializer_UnknownElement;
            serializer.UnknownAttribute += serializer_UnknownAttribute;
            return (T) serializer.Deserialize(new StringReader(xml));
        }

Ora è possibile eseguire qualsiasi stringa XML che si desidera convertire in un oggetto. Si può anche prendere qualsiasi oggetto e trasformarlo in una stringa XML:

        public static string ToXmlString<T>(this T obj)
        {
            using (var writer = new StringWriter())
            {
                obj.ToXml(writer);
                return writer.ToString();
            }
        }

        private static void ToXml<T>(this T obj, StringWriter writer)
        {
            new XmlSerializer(typeof (T)).Serialize(writer, obj);
        }

Quindi, questa è una chiara separazione. La classe originale è ancora decorata con gli attributi di serializzazione XML in modo che possa verificarsi la serializzazione XML. Se si vuole fare JSON o qualche altro formato, basta aggiungere quegli attributi (DataMember, ecc.) Alla classe originale in modo che possa avvenire la serializzazione JSOn.

Ancora una volta, se questo è solo un piccolo progetto, il tuo approccio va bene, ma per i progetti più grandi vorrei separarlo quando si tratta di potenzialmente da 10 a 100 di DTO.

    
risposta data 10.11.2016 - 16:28
fonte

Leggi altre domande sui tag