|
-
Jun 27th, 2011, 09:18 PM
#1
[.NET 2.0] Is Type/Structure Serializable
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!
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
It takes the "Type" of the structure, so, you would pass it like so:
Code:
Public Structure XYZ
End Structure
Console.WriteLine(IsStructureSerializable(Of XYZ))
Console.WriteLine(IsTypeSerializable(GetType(XYZ))
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!
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).
Last edited by formlesstree4; Jul 8th, 2011 at 11:02 AM.
Reason: Updated code and included two additional routines.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|