6
votes

C # Classe d'utilitaire de sérialisation générique

J'ai une classe existante pour sérialiser et désérialiser des objets à / de XML. C'est une classe générique avec un paramètre de type unique t dont la seule contrainte est où T: ixmlSerializable . Cependant, je souhaite toujours pouvoir utiliser cette classe sur des classes qui ne mettent pas implémenter ixmlSerializable mais ont le [sérialisable] attribut. Comment pourrais-je continuer à faire cela?

de ma classe générique: xxx

J'ai trouvé Cette discussion mais il n'y avait pas de solution donnée, juste que je ne peux pas faire où T: Serializable . Essayer de faire où T: SerializAbleatTtribute permet de dire Visual Studio Say "ne peut pas utiliser la classe scellée 'System.SerializaLeAssatribute' comme contrainte de paramètre de type".

EDIT: Basé sur Réponse de Stephen , j'ai supprimé les contraintes sur xmlSerializationUtils et ajouté ce constructeur statique: xxx


0 commentaires

4 Réponses :


6
votes

Vous ne pouvez pas nécessiter un attribut dans le cadre de génériques. Cependant, vous pouvez fournir un constructeur statique qui vérifie et je tire si ce n'est pas trouvé.


0 commentaires

6
votes

Je voudrais simplement éliminer la contrainte de type et attraperais la sérialisationException lorsque le type ne se difforme pas ou ne désérialisait pas correctement ... En fait, cela permet à vos méthodes génériques Serialize et désériorize d'accepter un formateur

public class Serialization
{
    public enum Formatter { Binary, Xml }

    #region Serialization methods
    public static void Serialize2File<T>(T obj, string pathSpec, 
        Formatter formatter)
    {
        try
        {
            switch (formatter)
            {
                case (Formatter.Binary):
                    using (var fs = new FileStream(pathSpec, FileMode.Create,
                                        FileAccess.Write, FileShare.Write))
                        (new BinaryFormatter()).Serialize(fs, obj);
                    break;

                case (Formatter.Xml):
                    var serializer = new XmlSerializer(typeof(T));
                    TextWriter textWriter = new StreamWriter(pathSpec);
                    serializer.Serialize(textWriter, obj);
                    textWriter.Close();
                    break;

                default:
                    throw new MyCustomException("Invalid Formatter option");
            }
        }
        catch (SerializationException sX)
        {
            var errMsg = String.Format(
                "Unable to serialize {0} into file {1}",
                obj, pathSpec);
            throw new MyCustomException(errMsg, sX);
        }
    }
    public static T DeSerializeFromFile<T>(string pathSpec, 
        Formatter formatter) where T : class
    {
        try
        {
            switch (formatter)
            {
                case (Formatter.Binary):
                    using (var strm = new FileStream(pathSpec,
                                        FileMode.Open, FileAccess.Read))
                    {
                        IFormatter fmt = new BinaryFormatter();
                        var o = fmt.Deserialize(strm);
                        if (!(o is T))
                            throw new ArgumentException("Bad Data File");
                        return o as T;
                    }

                case (Formatter.Xml):
                    var serializer = new XmlSerializer(typeof(T));
                    TextReader rdr = new StreamReader(pathSpec);
                    return (T)serializer.Deserialize(rdr);

                default:
                    throw new MyCustomException("Invalid Formatter option");
            }
        }
        catch (SerializationException sX)
        {
            var errMsg = String.Format(
                "Unable to deserialize {0} from file {1}",
                typeof(T), pathSpec);
            throw new MyCustomException(errMsg, sX);
        }
    }
    #endregion Serialization methods
}


4 commentaires

Ce n'est pas une solution déraisonnable.


Oui, je suis d'accord, il est utilisé par un développeur qui savoir si la classe qu'il tente de sérialiser est sérliasable, s'il l'utilise mal, ce qui correspond à des exceptions, vous ne pouvez pas éliminer tous les bugs posables au moment de la compilation.


@Ben: Nous ne pouvons pas toujours le faire, mais nous devrions certainement essayer d'attraper des bugs tôt et souvent. Dans ce cas, nous ne pouvons pas l'attraper au moment de la compilation, mais si nous utilisons le tour de constructeur statique, nous pouvons l'attraper au début du temps d'exécution (ce qui signifie qu'un chèque de fumée post-compilé ne le manquera pas).


Lorsque je suis origanlly codé cela, j'ai eu du code dans la classe à détecter (uniquement lors de la tentative de sérialisation XML), si la variable de type dépassée implémente ixmlSerializable ou (à l'aide de la réflexion), a été décorée avec le < Code> [Serializable] Attribut ... Puis WCF est sorti et ils ont ajouté l'attribut [Datacontract] , qui permet également un type de sérialisation en tant que XML. Alors j'ai enlevé ça ...



8
votes

Vous pouvez vérifier si un type est sérialisable à l'aide du ISSERIALISABLE Propriété du type de l'objet.

myObj.GetType().IsSerializable


3 commentaires

C'est mieux que de vérifier l'attribut. Merci.


Hm. Ma solution actuelle (dans ma question) vérifie si ixmlSerializable ou [Serializable] s'applique à la classe donnée t . Est-ce que est compte compte pour les deux?


Apparemment. Voir MSDN.MICROSSOFT.COM/EN-US/LIBRAY/...



0
votes

C # Catégorie d'utilité de sérialisation générique.

Le noyau de classes sérialisées qui implémentent l'attribut ixmlSerializable strud> ou Serializable strud> est de vérifier le type donné avant de le transmettre au sérialisateur . P>

using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.IO;
using System.Text;
using System.Xml.Schema;

namespace System
{
    public static partial class Extensions
    {
        /// <summary>
        /// Checks if the object <see cref="Type"/> has the specified attribute.
        /// </summary>
        /// <param name="type">
        /// Object <see cref="Type"/> for which you want to check whether
        /// whether it has <see cref="Attribute"/> specified by the <typeparamref name="T"/>.
        /// </param>
        public static bool HasAtribute<T>(this Type type) where T : Attribute
        {
            return type.GetCustomAttributes(typeof(T), true).Any();
        }
    
        /// <summary>
        /// Checks if the object <see cref="Type"/> implements the specified interface.
        /// </summary>
        /// <param name="type">
        /// Object <see cref="Type"/> for which you want to check whether
        /// whether it implements the interface specified by the <paramref name="interfaceType"/> parameter.
        /// </param>
        /// <param name="interfaceType">
        /// The <see cref="Type"/> being tested, which is an interface.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="type"/> is not a class, value type, or interface,
        /// and also if <paramref name="interfaceType"/> is not an interface.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The value <see langword="null"/> was passed as one of the parameters.
        /// </exception>
        /// <returns>
        /// <see langword="true"/> if the object <see cref="Type"/> implements the specified interface.
        /// </returns> 
        public static bool ImplementsInterface(this Type type, Type interfaceType)
        {
            if (type == null)
                throw new ArgumentNullException(nameof(type));
            if (interfaceType == null)
                throw new ArgumentNullException(nameof(interfaceType));
            if (!interfaceType.IsInterface)
                throw new ArgumentException("Argument must be interface.", 
                    nameof(interfaceType));

            while (type != null)
            {
                Type[] interfaces = type.GetInterfaces();
                {
                    int length = interfaces.Length;
                    for (int i = 0; i < length; i++)
                    {
                        if (interfaces[i] == interfaceType || interfaces[i].ImplementsInterface(interfaceType))
                            return true;
                    }
                }
                type = type.BaseType;
            }
            return false;
        }

        /// <summary>
        /// Checks if the object <see cref="Type"/> implements the specified interface.
        /// </summary>
        /// <typeparam name="T">
        /// The type being checked, which is an interface.
        /// </typeparam>
        /// <param name="type">
        /// Object <see cref="Type"/> for which you want to check whether
        /// whether it implements the specified interface <typeparamref name="T"/>.
        /// </param>
        /// <returns>
        /// <see langword="true"/> if the object is <see cref="Type"/>
        /// implements the <typeparamref name="T"/> interface.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="type"/> is not a class, value type, or interface.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The value <see langword="null"/> was passed as <paramref name="type"/>.
        /// </exception>
        public static bool ImplementsInterface<T>(this Type type) where T : class =>
            ImplementsInterface(type, typeof(T)); 

    }
}

namespace System.Xml.Serialization
{
    /// <summary>
    /// Serializes and deserializes <typeparamref name="T"/> objects into XML documents.
    /// Allows you to control the process of encoding objects in XML.
    /// </summary>
    /// <typeparam name="T">Object type.</typeparam>
    public static class XmlSerializer<T>
    {
        private static readonly XmlSerializer _serializer = new XmlSerializer(typeof(T));
        private static readonly XmlWriterSettings _defaultWriterSettings = new XmlWriterSettings
        {
            CheckCharacters = false,
            CloseOutput = false,
            ConformanceLevel = ConformanceLevel.Auto,
            Encoding = DefaultEncoding,
            Indent = true,
            IndentChars = "\t",
            NamespaceHandling = NamespaceHandling.OmitDuplicates,
            NewLineChars = "\r\n",
            NewLineHandling = NewLineHandling.Replace,
            NewLineOnAttributes = false,
            OmitXmlDeclaration = false
        };
        private static readonly XmlReaderSettings _defaultReaderSettings = new XmlReaderSettings
        {
            CheckCharacters = false,
            CloseInput = false,
            ConformanceLevel = ConformanceLevel.Auto,
            DtdProcessing = DtdProcessing.Prohibit,
            IgnoreComments = true,
            IgnoreProcessingInstructions = true,
            IgnoreWhitespace = true,
            LineNumberOffset = 0,
            LinePositionOffset = 0,
            MaxCharactersFromEntities = 0,
            MaxCharactersInDocument = 0,
            NameTable = null,
            ValidationFlags = XmlSchemaValidationFlags.None,
            ValidationType = ValidationType.None,
            XmlResolver = null
        };

        /// <summary>
        /// Default character encoding.
        /// </summary>
        public static Encoding DefaultEncoding => Encoding.UTF8;

        /// <summary>
        /// Default settings for the <see cref="XmlWriter" /> instance being created.
        /// </summary>
        public static XmlWriterSettings DefaultXmlWriterSettings => _defaultWriterSettings.Clone();

        /// <summary>
        /// Default settings for the <see cref="XmlReader" /> instance that is created.
        /// </summary>
        public static XmlReaderSettings DefaultXmlReaderSettings => _defaultReaderSettings.Clone();

        /// <summary>
        /// Serializes the given object and returns an XML document.
        /// </summary>
        /// <param name="o">
        /// An instance <typeparamref name="T"/> to serialize.
        /// </param>
        /// <param name="settings">
        /// Settings for the new <see cref="XmlWriter" /> instance.
        /// If <see langword="null"/> is specified,
        /// settings are used <see cref="DefaultXmlWriterSettings"/>.
        /// </param>
        /// <returns>An instance of <see cref="XmlDocument"/> that represents given object.</returns>
        public static XmlDocument Serialize(T o, XmlWriterSettings settings = null)
        {
            StringBuilder sb = new StringBuilder();
            using (XmlWriter xmlWriter = XmlWriter.Create(sb, settings ?? DefaultXmlWriterSettings))
                _serializer.Serialize(xmlWriter, o, (XmlSerializerNamespaces)null);
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(sb.ToString());
            return xmlDocument;
        }

        /// <summary>
        /// Deserializes the object contained in the specified XML document.
        /// </summary>
        /// <param name="xmlDocument">
        /// An XML document containing the serialized data.
        /// </param>
        /// <param name="settings">
        /// Settings for the new <see cref="XmlReader" /> instance.
        /// If <see langword="null"/> is specified,
        /// settings are used <see cref="DefaultXmlReaderSettings"/>.
        /// </param>
        /// <returns> The deserialized object of type <typeparamref name="T"/>. </returns>
        public static T Deserialize(XmlDocument xmlDocument, XmlReaderSettings settings)
        {
            string text = xmlDocument.OuterXml;
            using (StringReader reader = new StringReader(text))
            using (XmlReader xmlReader = XmlReader.Create(reader, DefaultXmlReaderSettings))
                return (T)_serializer.Deserialize(xmlReader);

        }

        /// <summary>
        /// Returns a value indicating whether this <see cref="XmlSerializer" /> can deserialize the specified XML document.
        /// </summary>
        /// <param name="xmlReader">
        /// <see cref="XmlReader" /> Pointing to the document to deserialize.
        /// </param>
        /// <returns>
        /// <see langword="true" /> If this <see cref="XmlSerializer" /> can deserialize an object, <see cref="XmlReader" /> indicates; otherwise, <see langword="false" />.
        /// </returns>
        public static bool CanDeserialize(XmlReader xmlReader)
        {
            return _serializer.CanDeserialize(xmlReader);
        }
    }
}


0 commentaires