Struttura System.Drawing.Font e XmlSerializer

Se si è provato a serializzare in XML la struttura System.Drawing.Font tramite un oggetto della classe System.Xml.Serialization.XmlSerializer si sarà notato che questa non viene serializzata correttamente. Il motivo dipende dal fatto che l’XmlSerializer richiede che l’oggetto da serializzare abbia un costruttore pubblico senza parametri come indicato nella KB330592 Error message when you serialize a class by using the XMLSerializer class: “System.InvalidOperationException”.

La classe System.Drawing.Color ha un costruttore senza parametri, ma privato e non pubblico.

Quindi se in una classe abbiamo una proprietà di tipo System.Drawing.Font che vogliamo serializzare possiamo usare definire una seconda proprietà che non tipo System.Drawing.Font, ma ad esempio di tipo stringa che andrà a impostare la proprietà System.Drawing.Font tramite il metodo System.Drawing.FontConverter.ConvertFromInvariantString. La proprietà System.Drawing.Font sarà quella che imposteremo a design time ad esempio tramite un PropertyGrid, ma non verrà serializzata impostando su di essa l’attributo System.Xml.Serialization.XmlIgnore. La proprietà stringa sarà invece la proprietà che verrà serializzata, ma per evitare confusioni non verrà visualizzata a design time decorandola con l’attributo System.ComponentModel.Browsable.

Di seguito un esempio tratto dall’applicazione .NET WinForms PowerTray che sto sviluppando a tempo perso e che ha l’obbiettivo di poter eseguire script PowerShell e di visualizzare l’output quando lo si desidera tramite una un’icona nella tray bar.

Public Shared ReadOnly Property DefaultOutputConsoleFont As System.Drawing.Font = System.Drawing.SystemFonts.DefaultFont

 

Private outputConsoleFontValue As System.Drawing.Font = PowerTraySettings.DefaultOutputConsoleFont

 

<System.Xml.Serialization.XmlIgnore()>
<System.ComponentModel.Category(GeneralCategory)>
<System.ComponentModel.DisplayName(“Output console font”)>
Public Property OutputConsoleFont As System.Drawing.Font

Get
Return Me.outputConsoleFontValue
End Get
Set(value As System.Drawing.Font)
Me.outputConsoleFontValue = value
End Set

End Property

 

Public Function ShouldSerializeOutputConsoleFont() As Boolean

Dim fc As New System.Drawing.FontConverter
Return Not (fc.ConvertToInvariantString(Me.outputConsoleFontValue) = fc.ConvertToInvariantString(PowerTraySettings.DefaultOutputConsoleFont))

End Function

 

Public Sub ResetOutputConsoleFont()

Me.outputConsoleFontValue = PowerTraySettings.DefaultOutputConsoleFont

End Sub

 

<System.ComponentModel.Browsable(False)>
Public Property OutputConsoleFontInvariantString As String

Get

Dim fc As New System.Drawing.FontConverter
Return fc.ConvertToInvariantString(Me.outputConsoleFontValue)

End Get
Set(value As String)

‘Il confronto eseguito con il metodo Equals restisce False per che la Proprietà GdiCharSet differisce
‘https://docs.microsoft.com/en-us/dotnet/api/system.drawing.font.equals
Dim fc As New System.Drawing.FontConverter
Me.outputConsoleFontValue = DirectCast(fc.ConvertFromInvariantString(value), System.Drawing.Font)

End Set

End Property

Public Function ShouldSerializeOutputConsoleFontInvariantString() As Boolean

Return Me.ShouldSerializeOutputConsoleFont()

End Function