代码之家  ›  专栏  ›  技术社区  ›  Sarah Vessels

C#泛型序列化实用程序类

  •  6
  • Sarah Vessels  · 技术社区  · 14 年前

    我有一个用于序列化和反序列化XML对象的现有类。它是一个泛型类,只有一个类型参数 T 唯一的限制是 where T : IXmlSerializable . 但是,我仍然希望能够在未实现的类上使用这个类 IXmlSerializable 但是你有 [Serializable]

    从我的泛型类:

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

    我发现 this discussion where T : Serializable . 试着去做 where T : SerializableAttribute 使Visual Studio说“不能将密封类'System.SerializableAttribute'用作类型参数约束”。

    基于 Stephen's answer ,我删除了 XmlSerializationUtils<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"
            );
        }
    }
    
    3 回复  |  直到 8 年前
        1
  •  6
  •   Steven Sudit    14 年前

        2
  •  8
  •   womp    14 年前

    IsSerializable 对象类型的属性。

    myObj.GetType().IsSerializable
    

    如前所述,这不可能作为泛型约束添加,但很可能在构造函数中进行检查。

        3
  •  6
  •   Charles Bretana    14 年前

    当类型没有正确序列化或反序列化时,我只需要消除类型约束并捕获SerializationException。。。实际上,这允许泛型序列化和反序列化方法接受格式化程序

    public enum Formatter { Binary, 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
    }