最近,我一直在学习序列化,所以我决定为我的应用程序编写一个小助手类,以便于在多个地方使用这个特性。实际上,我在代码中混合了一些泛型,并希望听到您对我的总体方法的反馈。
public class SerializationService
{
/// <summary>
/// This method Serializes the given Obj into an XML file.
/// </summary>
/// <param name="myObject">The obj to be serialized.</param>
/// <param name="fileFullPath">The file name with the full
/// path for the output serialized XML file.</param>
public static void SerializeToFile(Object myObject, string fileFullPath)
{
var xmlDoc = new XmlDocument();
var xmlSerializer = new XmlSerializer(myObject.GetType());
using (var fs = new FileStream(fileFullPath, FileMode.Create))
{
var writer = new XmlTextWriter(fs, Encoding.Unicode);
xmlSerializer.Serialize(writer, myObject);
writer.Close();
}
}
/// <summary>
/// This method deserializes the XML file into an Obj.
/// </summary>
/// <param name="fuleFullPath">The XML file to read.</param>
/// <returns>Deserialized obj of a type T.</returns>
public static T DeserializeToObj<T>(string fuleFullPath)
{
var xmlSerializer = new XmlSerializer(typeof(T));
using (var reader = new FileStream(fuleFullPath, FileMode.Open))
{
return (T) xmlSerializer.Deserialize(reader);
}
}
}下面是我如何在代码中使用它:
SerializationService.SerializeToFile(
_partRepository.GetParts().Where(p => p.IsIgnored).ToList(),
fileFullPath);var ignoredParts = SerializationService.DeserializeToObj<List<Part>>(ignoredPartsXml);发布于 2015-01-21 10:35:00
这里有几点评论。我不是完美的,也不是编写完美的代码,但我希望这些技巧将有助于编写更好的代码:
如果您的两个方法的名称有相反的名称,则更容易理解。例如:SerializeToFile和DeserializeFromFile。很明显,反序列化将返回一个对象,忽略名称中的对象。
另外,如果在一个方法中使用相同类型/类型的参数或变量,则在另一个方法中给它取相同的名称。
您也应该使序列化方法成为通用方法:
public static void SerializeToFile<T>(T obj, string fullPath)在point Type约束中,您将进一步了解其中的原因。
您应该尽可能地定义变量的用法。在您的示例中,您可以在XmlSerializer语句中实例化using类,因为在语句之外不需要它。示例:
using (var stream = new FileStream(fullPath, FileMode.Open))
{
var xmlSerializer = new XmlSerializer(typeof(T));
}在这两种方法中,都可以在某些情况下引发异常。在序列化方法中,如果路径不存在,您将得到一个DirectoryNotFoundException;在反序列化方法中,如果文件不存在,您将得到一个FileNotFoundException。这一问题很容易解决:
//Check for directory in serialize:
var directoryPath = Path.GetDirectory(fileFullPath);
var directoryExists = Directory.Exists(directoryPath);
//Check for file in deserialize
var fileExists = File.Exists(fileFullPath);你应该决定你想要正面的还是负面的评价。例如,只有在检查为正时才执行该方法,如果检查为否定,则抛出参数异常。那就看你的了。
另外,就像赫斯拉赫所说的:如果文件已经存在了怎么办?目前,该文件的内容将被新内容覆盖。
using语句:以下是:
using (var fs = new FileStream(fileFullPath, FileMode.Create))
{
var writer = new XmlTextWriter(fs, Encoding.Unicode);
xmlSerializer.Serialize(writer, myObject);
writer.Close();
}可代之以:
using (var stream = new FileStream(fullPath, FileMode.Create))
using (var writer = new XmlTextWriter(stream, Encoding.Unicode))
{
var xmlSerializer = new XmlSerializer(obj.GetType());
xmlSerializer.Serialize(writer, obj);
}还记得我让序列化方法也是通用的吗?现在,您不验证传入和传出对象。如果我传递一个没有公共无参数构造函数的类的实例,该怎么办?在运行时,我将得到一个InvalidOperationException,其消息如下:
..。无法序列化,因为它没有无参数的构造函数。
解决方案是在方法上放置类型约束。来自MSDN的定义:
定义泛型类时,可以将限制应用于客户端代码在实例化类时可用于类型参数的类型,这些限制称为约束。
您应该使用class和new()类型约束。他们的定义如下:
现在,当您尝试序列化没有公共无参数构造函数的clas实例时,您将得到一个编译时异常。您可以在这里阅读更多内容:关于类型参数的约束(C#编程指南)。
public static void SerializeToFile<T>(T obj, string fullPath) where T : class, new()
{
//method body
}
public static T DeserializeFromFile<T>(string fullPath) where T : class, new()
{
//method body
}所有这些应用之后,您的代码可能如下所示:
public class SerializationService
{
public static void SerializeToFile<T>(T obj, string fullPath) where T : class, new()
{
if(Directory.Exists(Path.GetDirectoryName(fullPath)))
{
using (var stream = new FileStream(fullPath, FileMode.Create))
using (var writer = new XmlTextWriter(stream, Encoding.Unicode))
{
var xmlSerializer = new XmlSerializer(obj.GetType());
xmlSerializer.Serialize(writer, obj);
}
}
}
public static T DeserializeFromFile<T>(string fullPath) where T : class, new()
{
if(File.Exists(fullPath))
{
using (var stream = new FileStream(fullPath, FileMode.Open))
{
var xmlSerializer = new XmlSerializer(typeof(T));
return (T) xmlSerializer.Deserialize(stream);
}
}
return default(T);
}
}发布于 2015-01-21 06:39:12
string fuleFullPath将是一个错误。DeserializeToObj上检查。如果没有,你应该抛出一个异常。SerializeToFile的策略。var xmlDoc = new XmlDocument();没有做任何事情,应该删除。DeserializeToObj()方法重命名为Deserialize()。很明显,它反序列化为一个对象。SerializeToFile()方法中,将FileStream对象fs命名为DeserializeToObj()方法,称为reader。发布于 2015-01-21 08:55:59
SerializeToFile也应该是通用的。序列化方法在Object上工作似乎很奇怪,而反序列化方法是泛型的。https://codereview.stackexchange.com/questions/78191
复制相似问题