I had a recent need for checking if a structure, and all the members inside of it, were serializable to avoid throwing a serialization exception on certain systems -where throwing one would be very costly, and in a situation where I might not know exactly what's being passed through the stream and attempting to be serialized.
So after loads of google searching, I only found various ideas on how to do such a thing, mostly checking the single instance or the main structure itself. I can mark that as serializable, but what if one of the types inside isn't? Say, for some reason, the structure contains a TcpClient, or a MemoryStream. Neither of those is technically serializable and would throw an exception when attempting to be serialized.
Finally, after a bit of experimenting in Visual Studio and with plenty of help from IntelliSense, I found a way to finally do it!
It takes the "Type" of the structure, so, you would pass it like so:Code:''' <summary> ''' Determines if a structure is serializable. ''' </summary> ''' <typeparam name="T">The structure to test.</typeparam> ''' <returns>A boolean indicating if the structure can be serialized.</returns> ''' <remarks>It's really simple to check. If your structure is Foo, then you simply call the function as so: ''' IsStructureSerializable(Of Foo), and you will get a boolean value.</remarks> Public Function IsStructureSerializable(Of T As Structure)() As Boolean 'Just a wrapper around the IsTypeSerializable. Return IsTypeSerializable(GetType(T)) End Function ''' <summary> ''' Determines if a class is serializable. ''' </summary> ''' <typeparam name="T">The class to test.</typeparam> ''' <returns>A boolean indicating if the class can be serialized.</returns> ''' <remarks>It's pretty simple to check. If your class is called Foo, then you simply call the function as so: ''' IsClassSerializable(Of Foo), and you will get a boolean value.</remarks> Public Function IsClassSerializable(Of T As Class)() As Boolean 'Just a wrapper around the IsTypeSerializable. Return IsTypeSerializable(GetType(T)) End Function ''' <summary> ''' Loops through the entire object to see if it is indeed serializable. ''' </summary> ''' <param name="type">The object Type to check.</param> ''' <returns>A boolean that indicates if the object passed is able to be successfully serialized.</returns> ''' <remarks>This function is recursive and will ignore any fields marked as "NonSerialized". ''' However, if at any time there is a field that cannot be serialized, and it is not marked as "NonSerialized", the routine will end and immediately return false.</remarks> Public Function IsTypeSerializable(ByVal type As [Type]) As Boolean 'Final serializable result Dim _result As Boolean = True 'Make sure our current type is serializable If type.IsSerializable Then 'Ok, so now get any sub-fields. Dim _subFields() As Reflection.FieldInfo = type.GetFields(Reflection.BindingFlags.Instance Or Reflection.BindingFlags.DeclaredOnly Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.NonPublic) 'Loop each subfield For Each _field As Reflection.FieldInfo In _subFields 'Get the type Dim _type As Type = _field.FieldType 'See some details about this. Console.WriteLine("-------------------------------") Console.WriteLine(String.Format("Checking Type: {0}", _type.ToString())) Console.WriteLine("Name: {0}", _field.Name) Console.WriteLine("Private: {0}", _field.IsPrivate) Console.WriteLine("Public: {0}", _field.IsPublic) Console.WriteLine("Static: {0}", _field.IsStatic) Console.WriteLine("Primitive: {0}", _type.IsPrimitive) 'Get an object array to see if this type is marked as NonSerialized. Dim _attribues() As Object = _field.GetCustomAttributes(GetType(NonSerializedAttribute), False) 'Check If _attribues IsNot Nothing AndAlso _attribues.Length > 0 Then 'This is to be ignored! Console.WriteLine("Type {0} is marked for NonSerializable!", _field.ToString) Else 'Check if it's a primitive If _type.IsPrimitive Then 'It is. _result = True Else 'We have to go deeper. _result = IsTypeSerializable(_type) End If End If 'Write out the result Console.WriteLine("Type {0} {1} serializable", _type.ToString(), If(_result AndAlso _attribues.Length.Equals(0), "is", "is not")) Console.WriteLine("-------------------------------") Console.WriteLine() 'Check If Not _result Then Exit For Next Else 'The structure is not serializable _result = False End If 'Give back the result Return _result End Function
The code will retrieve Private, Public, Static or Protected variables in a class or structure and, as far as I know, should always work. If there are any problems, please let me know!Code:Public Structure XYZ End Structure Console.WriteLine(IsStructureSerializable(Of XYZ)) Console.WriteLine(IsTypeSerializable(GetType(XYZ))
EDIT: Updated with a suggestion from Nick (who was gracious enough to provide an example on how to do it! Thanks Nick!)
EDIT 2: Another update with overloads (suggested by Nick awhile back...I just got lazy).


Reply With Quote
But yeah if it's only for structures then it should work. As for private fields not being fields, aren't they? He is explicitly checking for non-public fields as well, I would assume that includes private fields?

I guess what he says here is correct (assuming it does indeed get private fields as well as I would think) but if you passed a class it wouldn't check the properties.
