我有一个现有的类,用于对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'作为类型参数约束”。
修改,我删除了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"
);
}
}
答案 0 :(得分:8)
您可以使用对象类型的IsSerializable属性检查类型是否可序列化。
myObj.GetType().IsSerializable
如上所述,这不可能作为通用约束添加,但最有可能在构造函数中检查。
答案 1 :(得分:6)
您不能要求属性作为泛型的一部分。但是,您可以提供一个静态构造函数来检查它,如果找不到则抛出它。
答案 2 :(得分:5)
我只是消除了类型约束并在类型没有正确序列化或反序列化时捕获SerializationException ...事实上,这允许你的通用Serialize和Deserialize方法接受格式化程序
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
}