English 中文(简体)
C# 通用序列化公用事业
原标题:C# generic serialization utility class

我拥有从XML到(XML)的序列化和分化物体的现有类别。 具有单一类型参数的普通类别<代码>。 T 唯一的制约因素是<代码>,T:IXmlSerializable。 然而,我仍然能够在不执行<代码>IXmlSerializable<>/code>但有[Serializable]的类别上使用这一类别。 我怎么办?

从我的普通类别来看:

public static class XmlSerializationUtils<T> where T : IXmlSerializable
{
    public static T DeserializeXml(XmlDocument xml) { ... }
    public static XmlDocument SerializeToXml(T toSerialize) { ... }
}

我发现,这一讨论,但没有给出解决办法,只是我可以 t到, T :Serializable。 T :SerializableAttribute, 视力演播室说“没有使用密封级系统”。 空中可加固作为参数限制。

Edit: based on Stephen swer, Imoved restrictions on XmlSerialization Utils<T>,并添加这一固定构造:

static XmlSerializationUtils()
{
    Type type = typeof(T);
    bool hasAttribute = null != Attribute.GetCustomAttribute(type,
        typeof(SerializableAttribute));
    bool implementsInterface =
        null != type.GetInterface(typeof(IXmlSerializable).FullName);
    if (!hasAttribute && !implementsInterface)
    {
        throw new ArgumentException(
            "Cannot use XmlSerializationUtils on class " + type.Name +
            " because it does not have the Serializable attribute " +
            " and it does not implement IXmlSerializable"
        );
    }
}
最佳回答

你们不需要作为非专利的一部分的归属。 然而,如果找不到,你可以提供固定的构造,对它进行检查和投掷。

问题回答

I d 只是消除类型限制,在这种类型没有适当序列化或脱硫时捕获。 事实上,这允许你采用通用的航空和航天方法接受一种格式

public enum Formatter { Binary, Xml }

能够控制序列化是双倍还是Xml

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
}

C# generic serialization utility class.

执行IXmlSerializableSerializable的序列核心是检查特定类型,然后将其交给序列仪。

XmlDocument Serialize<T>(T obj)
{
    Type type = typeof(T);
    if (type.HasAttribute<SerializableAttribute>()
      | type.ImplementsInterface<IXmlSerializableAttribute>())
        return XmlSerializer<T>.Serialize(obj);
    throw new InvalidOperationException("Unserializable object given.");
}        

为此,您应采用以下推广方法和通用序列器。

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 = "	",
            NamespaceHandling = NamespaceHandling.OmitDuplicates,
            NewLineChars = "
",
            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);
        }
    }
}




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...