I found a working code serialization of controls, but it has not one function: there is a controls, the controls has an event, after saving it does not saves. How can I solve this problem?
Following is the code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
namespace serial
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Save control
int i = 0;
foreach (XElement element in
panel1.Controls
.OfType<Control>()
.Select(ToXml))
{
element.Save("Control" + i++ + ".xml");
}
}
private static XElement ToXml(Control control)
{
Type controlType = control.GetType();
var root = new XElement("Root",
new XAttribute("Type", controlType.AssemblyQualifiedName));
PropertyInfo[] fieldInfos = controlType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo fieldInfo in fieldInfos)
{
if (fieldInfo.CanRead && fieldInfo.CanWrite &&
fieldInfo.Name != "Font" && fieldInfo.Name != "Handle")
{
object content = fieldInfo.GetValue(control, null);
if (content != null && content.GetType().IsSerializable)
{
var serializer = new DataContractSerializer(content.GetType());
var str = new StringBuilder();
using (XmlWriter stream = XmlWriter.Create(str))
{
serializer.WriteObject(stream, content);
}
XElement data = XElement.Parse(str.ToString());
var element = new XElement("Property",
new XAttribute("Name", fieldInfo.Name),
new XAttribute("Type", fieldInfo.PropertyType.AssemblyQualifiedName)
, data);
root.Add(element);
}
}
}
return root;
}
private void button2_Click(object sender, EventArgs e)
{
panel1.Controls.Clear();
}
private void button3_Click(object sender, EventArgs e)
{
// Clear panel
panel1.Controls.Clear();
// Load control
IEnumerable<string> newControlsNames = Directory.EnumerateFiles(Environment.CurrentDirectory, "*.xml");
Control[] newControls = newControlsNames
.Select(XElement.Load)
.Select(GetControl)
.Select(c => c as Control)
.ToArray();
// Add control on panel
panel1.Controls.AddRange(newControls);
}
// get control from xml
private static object GetControl(XElement xml)
{
Type controlType = Type.GetType(xml.Attribute("Type").Value);
object control = Activator.CreateInstance(controlType);
IEnumerable<XElement> elements = xml.Elements("Property");
foreach (XElement element in elements)
{
string name = element.Attribute("Name").Value;
Type type = Type.GetType(element.Attribute("Type").Value);
XNode first = elem开发者_如何学Goent.Nodes().First();
var serializer = new DataContractSerializer(type);
object value;
using (var stream = new MemoryStream(Encoding.Default.GetBytes(first.ToString())))
{
value = serializer.ReadObject(stream);
}
if (value != null)
{
PropertyInfo fieldInfo = controlType.GetProperty(name);
fieldInfo.SetValue(control, value, null);
}
}
return control;
}
private void button4_Click(object sender, EventArgs e)
{
MessageBox.Show("1");
}
private void button5_MouseEnter(object sender, EventArgs e)
{
MessageBox.Show("2");
}
}
}
edit: Here's my project! http://www.fileserve.com/file/t7kUwWM
The problem with evets is, the list of delegates are not accesible from "outside" the class. There is workaround - must use reflection and search for private fields typed as delegate (I mean custom delegate not only System.Delegate) and than serialize references to target object and target method (via System.Reflection.MethodInfo).
However this solution is very proprietary and does not guarantee the correct behaviour in all cases, because depends on private state of object.
精彩评论