控件全属性(反)序列化难题:寻求简便实现方案
控件属性序列化的简化实现方案
问题场景
尝试对控件所有属性进行序列化,测试DevExpress TextEdit和TextBox控件时发现:仅无子项或非枚举类型的属性可直接通过(反)序列化转换为字符串完成操作。目前手动为各控件属性编写单独规则工作量极大,尤其兼容不同厂商控件时难度更高,求更简便的实现方式。
当前实现代码(VB.NET)
Public Class ControlProperties Public Property Text As String Public Property BackColor As String Public Property BorderStyle As Integer Public Property Size As Size Public Property Location As Point Public Property ForeColor As String Public Property Multiline As Boolean Public Property AllowDrop As Boolean Public Property Cursor As String Public Property RightToLeft As RightToLeft Public Property Font As SerializableFont End Class Public Class SerializableFont Public Property Name As String Public Property Size As Single Public Property Style As FontStyle Public Sub New() End Sub Public Sub New(font As Font) Name = font.Name Size = font.Size Style = font.Style End Sub Public Function ToFont() As Font Return New Font(Name, Size, Style) End Function End Class Public Sub SerializeControlProperties(control As Object, filePath As String) Dim properties As New ControlProperties() properties.Text = control.Text properties.BackColor = ColorTranslator.ToHtml(control.BackColor) properties.BorderStyle = control.BorderStyle properties.Size = control.Size properties.Location = control.Location properties.ForeColor = ColorTranslator.ToHtml(control.ForeColor) properties.AllowDrop = control.AllowDrop properties.Cursor = CursorToString(control.Cursor) properties.RightToLeft = control.RightToLeft properties.Font = New SerializableFont(control.Font) Dim serializer As New XmlSerializer(GetType(ControlProperties)) Using writer As TextWriter = New StreamWriter(filePath) serializer.Serialize(writer, properties) End Using End Sub
生成的XML示例
<?xml version="1.0" encoding="utf-8"?> <ControlProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Text /> <BackColor>#FFFFFF</BackColor> <BorderStyle>7</BorderStyle> <Size> <Width>100</Width> <Height>20</Height> </Size> <Location> <X>221</X> <Y>26</Y> </Location> <ForeColor>#282828</ForeColor> <Multiline>false</Multiline> <AllowDrop>false</AllowDrop> <Cursor>System.Windows.Forms.Cursor</Cursor> <RightToLeft>No</RightToLeft> <Font> <Name>Tahoma</Name> <Size>8.25</Size> <Style>Regular</Style> </Font> </ControlProperties>
简化实现方案
1. 利用反射自动遍历属性,减少手动赋值
通过反射获取控件公共属性,自动判断类型并处理序列化转换,无需手动定义ControlProperties类:
Imports System.Reflection Imports System.Xml.Serialization Public Sub SerializeControlByReflection(control As Control, filePath As String) Dim overrides As New XmlAttributeOverrides() ' 注册Color、Font、Cursor的自定义序列化逻辑 AddColorSerializer(overrides) AddFontSerializer(overrides) AddCursorSerializer(overrides) Dim serializer As New XmlSerializer(control.GetType(), overrides) Using writer As New StreamWriter(filePath) serializer.Serialize(writer, control) End Using End Sub Private Sub AddColorSerializer(overrides As XmlAttributeOverrides) Dim colorAttrs As New XmlAttributes() colorAttrs.XmlSerializer = New XmlSerializer(GetType(String)) overrides.Add(GetType(Color), colorAttrs) End Sub Private Sub AddFontSerializer(overrides As XmlAttributeOverrides) Dim fontAttrs As New XmlAttributes() fontAttrs.XmlSerializer = New XmlSerializer(GetType(SerializableFont)) overrides.Add(GetType(Font), fontAttrs) End Sub Private Sub AddCursorSerializer(overrides As XmlAttributeOverrides) Dim cursorAttrs As New XmlAttributes() cursorAttrs.XmlSerializer = New XmlSerializer(GetType(String)) overrides.Add(GetType(Cursor), cursorAttrs) End Sub
2. 复用第三方控件自带的序列化机制
多数第三方控件(如DevExpress)自带布局序列化方法,直接调用即可:
' DevExpress TextEdit序列化示例 Dim textEdit As New DevExpress.XtraEditors.TextEdit() textEdit.SaveLayoutToXml("textEditLayout.xml") ' 反序列化 textEdit.RestoreLayoutFromXml("textEditLayout.xml")
WinForms原生控件可借助System.ComponentModel.TypeDescriptor获取属性的序列化字符串,或复用PropertyGrid的序列化能力。
3. 使用Json.NET替代XmlSerializer,简化复杂类型处理
Json.NET对WinForms复杂类型支持更友好,仅需少量自定义转换器:
Imports Newtonsoft.Json Imports Newtonsoft.Json.Converters ' 自定义Color转换器 Public Class ColorConverter Inherits JsonConverter(Of Color) Public Overrides Sub WriteJson(writer As JsonWriter, value As Color, serializer As JsonSerializer) writer.WriteValue(ColorTranslator.ToHtml(value)) End Sub Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Color, hasExistingValue As Boolean, serializer As JsonSerializer) As Color Return ColorTranslator.FromHtml(reader.Value.ToString()) End Function End Class ' 自定义Font转换器 Public Class FontConverter Inherits JsonConverter(Of Font) Public Overrides Sub WriteJson(writer As JsonWriter, value As Font, serializer As JsonSerializer) serializer.Serialize(writer, New SerializableFont(value)) End Sub Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Font, hasExistingValue As Boolean, serializer As JsonSerializer) As Font Dim serializableFont = serializer.Deserialize(Of SerializableFont)(reader) Return serializableFont.ToFont() End Function End Class ' 序列化示例 Public Sub SerializeControlToJson(control As Control, filePath As String) Dim settings As New JsonSerializerSettings() settings.Converters.Add(New ColorConverter()) settings.Converters.Add(New FontConverter()) settings.Formatting = Formatting.Indented Dim json = JsonConvert.SerializeObject(control, settings) File.WriteAllText(filePath, json) End Sub
4. 封装通用序列化工具类
将类型转换逻辑封装成通用方法,注册一次转换器即可复用,无需为每个控件编写单独规则。
内容的提问来源于stack exchange,提问作者nidzolino
相关产品推荐
相关产品推荐

