I have a Generic class that takes an object of type T, serializes it as XML, then saves it to the filesystem. Currently however the serialize operation fails if the object is not serializable. That’s not a problem as such, however I think it would be better to check in my class constructor whether an instance of T is serializable or not and if it is not, throw an error at that point rather than later on.
Is there a way of checking of an instance of T can be serialized as XML other than simply instantiating it and trying to serialize it in a TRY…CATCH? It would be nice if I could interrogate the class T in some manner to discover whether it can be serialized as XML or not.
If it helps, the code can be seen here: http://winrtstoragehelper.codeplex.com/SourceControl/changeset/view/ac24e6e923cd#WinRtUtility%2fWinRtUtility%2fObjectStorageHelper.cs
Note that this code gets compiled against WinRT (i.e., it is for use in a Windows 8 app) however I think the question is relevant to any dialect of C#.
thanks in advance
Jamie
AFAIK, even if you check for various attributes (
Serializable,DataContract) or check for theType.IsSerializable(which I believe is just a convenience method for checking theSerializableattribute’s existence) it doesn’t guarantee that the implementation actually is serializable. (EDIT: As mentioned, and seen in the example code provided in the question,XmlSerializerdoes not depend on theSerializableattribute adornment. So there’s no sense in checking for these flags.)In my experience, your best bet is to use unit tests that will validate the various types used in your application and use try/catch to see if it pass/fails. At runtime, use try/catch (rather than pre-checking each time) and log/handle the exception.
If you have a list of valid compatible types as a result of your unit-testing, you can have a pre-check of
Tagainst a compile-time list that you determined from testing previously and assume any other types are just no good. Might want to watch for subclasses of known valid types though as even if they inherit from a valid serializable type, their implementation may not be.EDIT: Since this is for Windows Phone 8, while I don’t have experience with that platform, I have worked with Silverlight. And in that case, you can serialize objects even if they are not marked as
[Serializable](in fact, it doesn’t even exist in Silverlight). The built-inXmlSerializerjust works against all public properties regardless of adornment. The only way to see if it’s serializable is either attempt a serialization and try/catch the failure, or write an algorithm to inspect each property (and recursively through child objects) and check if each type can be serialized.EDITx2: Looking at your
ObjectStorageHelper, I would suggest that you simply attempt serialization and catch any failures. You don’t necessarily have to bubble up the exception directly. You could wrap with your own custom exception or have a returned results object that informs the API consumer of the pass/fail of the serialization and why it may have failed. Better to assume the caller is using a valid object rather than doing an expensive check each time.EDITx3: Since you’re doing a lot of other work in the save method, I would suggest rewriting your code like this:
This way you catch the serialization issue specifically and can report to the API consumer very clearly that they have provided an invalid/non-serializable object. This way if you have an exception being thrown as part of your I/O portions, it’s clearer where the issue is. In fact, you may want to separate out the serialization/deserialization aspects to their own discrete method/class so you can feed in other serializers (or be more clear from the stack trace where the issue is, or simply to make your methods do one thing and one thing only) But any more rewriting/refactoring is really left for code-review anyway and not valid much for the question at hand.
FYI, I also put a null check for your input object because if the user passes null, they would think that the save was successful when in fact, nothing happened and they might expect a value to be available for loading later when it doesn’t exist. If you want to allow nulls as valid values, then don’t bother with
the checkthrowing an error.