我正在尝试从配置文件中序列化一些自定义设置。 以下是我的设置:
<FavouriteTools>
<favouriteTool PluginPlaceHolder="FavoriteTool1" PlugInName="Brightness"
PlugInType="2D" PlugInAssemblyName="Micro.DigiMic.Plugins.AreaBasedOnBrightness.AreaBasedOnBrightnessPlugin"
GUID="0000c03a-b891-4ebd-87d7-5fbc19073a1a" />
<favouriteTool PluginPlaceHolder="FavoriteTool2" PlugInName="CircleArea"
PlugInType="2D" PlugInAssemblyName="Micro.DigiMic.Plugins.CircleAreaPlugin.CircleAreaPlugin"
GUID="0000c06a-b891-4ebd-87d7-5fbc19073a1a" />
<favouriteTool PluginPlaceHolder="FavoriteTool3" PlugInName="Contour Area"
PlugInType="2D" PlugInAssemblyName="Micro.DigiMic.Plugins.ContourAreaPlugin.ContourAreaPlugin"
GUID="0000c11a-b891-4ebd-87d7-5fbc19073a1a" />
但是在序列化它时会出错。这是我的课程。
//FavouriteTools - Root Node
[Serializable]
[XmlType("FavoriteTools")]
[ConfigurationCollection(typeof(FavouriteTool), AddItemName = "favouriteTool", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class FavouriteToolsCollection
: ConfigurationElementCollection
{
//Few plublic methods here
}
//favouriteTool - Child node
[Serializable]
[XmlType("favouriteTool")]
public class FavouriteTool : ConfigurationElement
{
/// <summary>
/// Gets or sets value of Plugin PlaceHolder.
/// </summary>
/// <value>Text Color.</value>
[ConfigurationProperty("PluginPlaceHolder", IsRequired = false)]
public string PlugPlaceHolder
{
get { return (string)base["PluginPlaceHolder"]; }
set { base["PluginPlaceHolder"] = value; }
}
//Few more properties like above
}
I am trying to serialize below class, but gets exception on below like
XmlSerializer xmlinf = new XmlSerializer(data.GetType());
`data` is `ExportUser`
[Serializable]
public class ExportUser
{
public bool IsMetric { get; set; }
[XmlArray("FavoriteTools")]
[XmlArrayItem("favouriteTool")]
public FavouriteToolsCollection FavoriteTools { get; set; }
}
我收到此错误 - There was an error reflecting type 'ExportUser'
并在内部异常中显示错误 - There was an error reflecting type 'FavoriteTools'
。
有什么遗漏吗?
更新
看到内部异常后,错误是
{"You must implement a default accessor on System.Configuration.ConfigurationLockCollection because it inherits from ICollection."}
There was an error reflecting type 'Zeiss.Micro.DigiMic.Application.FavouriteTool'.
但我在FavouriteToolsCollection
类中有一个默认访问者:
public FavouriteTool this[int index]
{
get
{
return (FavouriteTool)BaseGet(index);
}
set
{
if (this.BaseGet(index) != null)
{
this.BaseRemoveAt(index);
}
this.BaseAdd(index, value);
}
}
还缺少什么?
答案 0 :(得分:0)
行。我刚遇到这个。并使用包装器对象解决了它。
我所做的是为我想要的东西创建一个简单的包装器对象 连载。我的情况是它是一个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;
}
}