好的。我刚遇到这个。并使用包装器对象解决了它。
我所做的是为我想要序列化的东西创建一个简单的包装对象。我的情况是一个ConfigurationCollection。我对其进行序列化并创建几个适配器以从可序列化对象映射到实际对象,反之亦然。
using system.Xml.Serialization;
// This is an XML wrapper for FolderElement.
public class FolderAttributes
{
[XmlAttribute("Name")]
public string Name { get; set; }
[XmlAttribute("Volume")]
public string Volume { get; set; }
[XmlAttribute("Path")]
public string Path { get; set; }
[XmlAttribute("Selected")]
public bool Selected { get; set; }
[XmlAttribute("Active")]
public bool Active { get; set; }
/// <summary>
/// Factory Method.
/// Create new instance of FolderAttributes from FolderElment.
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
public static FolderAttributes FromElement(FolderElement element)
{
return new FolderAttributes()
{
Name = element.Name,
Volume = element.VolumeLabel,
Path = element.Path,
Selected = element.Selected,
Active = element.Active
};
}
/// <summary>
/// Convert this instance to a FolderElement.
/// </summary>
/// <returns></returns>
public FolderElement ToElement()
{
return new FolderElement()
{
Name = Name,
VolumeLabel = Volume,
Path = Path,
Selected = Selected,
Active = Active
};
}
}
public class FolderElement : ConfigurationElement
{
protected const string NameKey = "name";
protected const string VolumeKey = "volume";
protected const string PathKey = "path";
protected const string selectedKey = "selected";
protected const string activeKey = "active";
[ConfigurationProperty(NameKey, DefaultValue = "", IsKey = true, IsRequired = true)]
public string Name
{
get { return (string)base[NameKey]; }
set { base[NameKey] = value; }
}
[ConfigurationProperty(VolumeKey, DefaultValue = "", IsKey = false, IsRequired = false)]
public string VolumeLabel
{
get { return (string)base[VolumeKey]; }
set { base[VolumeKey] = value; }
}
[ConfigurationProperty(PathKey, DefaultValue = "", IsKey = false, IsRequired = true)]
public string Path
{
get { return (string)base[PathKey]; }
set { base[PathKey] = value; }
}
[ConfigurationProperty(selectedKey, DefaultValue = "false", IsKey = false, IsRequired = false)]
public bool Selected
{
get { return (bool)base[selectedKey]; }
set { base[selectedKey] = value; }
}
[ConfigurationProperty(activeKey, DefaultValue = "true", IsKey = false, IsRequired = false)]
public bool Active
{
get { return (bool)base[activeKey]; }
set { base[activeKey] = value; }
}
}
[ConfigurationCollection(typeof(FolderElement))]
public class FolderCollection : ConfigurationElementCollection
{
internal const string _elementName = "elements";
protected override string ElementName
{
get { return _elementName; }
}
public override ConfigurationElementCollectionType CollectionType
{
get { return ConfigurationElementCollectionType.AddRemoveClearMap; }
}
protected override bool IsElementName(string elementName)
{
return elementName.Equals(_elementName, StringComparison.InvariantCultureIgnoreCase);
}
public override bool IsReadOnly()
{
return false;
}
protected override ConfigurationElement CreateNewElement()
{
return new FolderElement();
}
/// <summary>
/// Return key value for element.
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
/// <remarks></remarks>
protected override object GetElementKey(ConfigurationElement element)
{
return ((FolderElement)element).Name;
}
/// <summary>
/// Default index property.
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public FolderElement this[int index]
{
get { return (FolderElement)BaseGet(index); }
}
/// <summary>
/// Returns content element by name.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public FolderElement GetElementByName(string name)
{
return (FolderElement)BaseGet(name);
}
public IEnumerable<FolderElement> Elements
{
get
{
for (int index = 0; index < this.Count; index++) yield return (FolderElement)BaseGet(index);
}
}
/// <summary>
/// Add an element to the collection
/// </summary>
/// <param name="element"></param>
public void AddElement(FolderElement element)
{
BaseAdd(element);
}
}
public class FolderSection : ConfigurationSection
{
// Attribute argument must be a constant expression.
protected const string _elementsTag = "elements";
[ConfigurationProperty(_elementsTag, Options = ConfigurationPropertyOptions.IsDefaultCollection)]
public FolderCollection Elements
{
get { return ((FolderCollection)(base[_elementsTag])); }
set { base[_elementsTag] = value; }
}
public void SaveElements(ConfigurationElementCollection elements, string path)
{
var container = new List<FolderAttributes>();
foreach (FolderElement element in elements)
{
container.Add(FolderAttributes.FromElement(element));
}
// XmlHelper.SaveXml(container, path);
SaveXml(container, path);
}
/// <summary>
/// Load elements from xml file pointed to by path.
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public List<FolderElement> LoadElements(string path)
{
List<FolderElement> result = new List<FolderElement>();
var attributes = Deserialize<List<FolderAttributes>>(path);
if (attributes != null)
{
foreach (var attr in attributes)
{
var element = attr.ToElement();
result.Add(element);
}
}
return result;
}
/// <summary>
/// Save XML serialization of object to named file.
/// </summary>
/// <param name="value"></param>
/// <param name="fileName"></param>
public static void SaveXml(Object value, string fileName)
{
// First serialize the object to memory stream,
// in case of exception, the original file is not corrupted
using (MemoryStream ms = new MemoryStream())
{
var stream = new System.IO.StreamWriter(ms);
if (Serialize(value, stream))
{
// if the serialization succeeded, rewrite the file.
File.WriteAllBytes(fileName, ms.ToArray());
}
}
}
/// <summary>
/// Base-level method to serialize object to TextWriter.
/// </summary>
/// <param name="value"></param>
/// <param name="output"></param>
/// <returns></returns>
public static bool Serialize<T>(object value, TextWriter output)
{
if (value == null) throw new ArgumentNullException("Serialize(value)");
bool result = false;
Type T = value.GetType();
try
{
var xmlSerializer = new XmlSerializer(typeof(T));
using (var xmlWriter = XmlWriter.Create(output, new XmlWriterSettings { Indent = true }))
{
xmlSerializer.Serialize(xmlWriter, value);
result = true;
}
}
catch (Exception)
{
// Log.Error(ex, "WriteXml {0}", T.Name);
}
return result;
}
public static T Deserialize<T>(string fileName)
{
T result = default(T);
try
{
using (var stream = System.IO.File.OpenRead(fileName))
{
var serializer = new XmlSerializer(typeof(T));
result = (T)serializer.Deserialize(stream);
}
}
catch (Exception)
{
// Log.Error(ex, "Deserialize<{0}> from file {1}", typeof(T).Name, fileName);
}
return result;
}
}