Can anyone recommend a way to check if a class can be serialized as XML?

I have a Generic class that takes an object of type T, serializes it as XML, and then saves it to the file system. However, the serialization operation is not currently performed if the object is not serializable. This is not a problem as such, however, I think it would be better to check in my class constructor whether the instance of T is serializable or not, and if not, then issue an error at this point, and not later.

Is there a way to validate an instance of T can be serialized as XML, and not just an instance of it and trying to serialize it to TRY ... CATCH? It would be nice if I could interrogate the T class in some way to find out if it can be serialized as XML or not.

If this helps, the code can be seen here: http://winrtstoragehelper.codeplex.com/SourceControl/changeset/view/ac24e6e923cd#WinRtUtility%2fWinRtUtility%2fObjectStorageHelper.cs

Please note that this code compiles with WinRT (i.e. it is used in a Windows 8 application), however I think this question is relevant to any C # dialect.

early

Jamie

+6
source share
2 answers

AFAIK, even if you check various attributes ( Serializable , DataContract ) or check Type.IsSerializable (which, I think, is just a convenient method for checking the existence of the Serializable attribute), it does not guarantee that the implementation is actually serializable. (EDIT: As already mentioned, and in the code example presented in the question, the XmlSerializer is independent of the Serializable attribute decoration. Therefore, it makes no sense to check these flags.)

In my experience, it is best to use unit tests that will check the various types used in your application and use try / catch to see if it passes. At run time, use try / catch (rather than pre-checking each time) and catch / handle the exception.

If you have a list of valid compatible types as a result of testing your device, you can pre-test T against the compilation time list you defined earlier and assume that any other types are just not good. You might want to keep track of subclasses of known valid types, although even if they inherit from a valid serializable type, their implementation may not be the same.

EDIT: since this is for Windows Phone 8, although I have no experience with this platform, I worked with Silverlight. And in this case, you can serialize objects even if they are not marked as [Serializable] (in fact, it does not even exist in Silverlight). The built-in XmlSerializer simply works against all public properties regardless of decoration. The only way to find out if it is serializing, or try to serialize, or try / catch a failure, or write an algorithm to check each property (and recursively through child objects) and check whether each type can be serialized.

EDITx2: Looking at your ObjectStorageHelper , I suggest you just try serializing and catching any crashes. You do not have to just throw an exception. You can either wrap your own custom exception or get a return result object that informs the consumer API about the progress / failure of serialization and why it might have failed. It is better to assume that the caller is using a valid object rather than performing an expensive check every time.

EDITx3: Since you do most of the other work in the save method, I would suggest rewriting the code as follows:

 public async Task SaveAsync(T Obj) { if (Obj == null) throw new ArgumentNullException("Obj"); StorageFile file = null; StorageFolder folder = GetFolder(storageType); file = await folder.CreateFileAsync(FileName(Obj), CreationCollisionOption.ReplaceExisting); IRandomAccessStream writeStream = await file.OpenAsync(FileAccessMode.ReadWrite); using (Stream outStream = Task.Run(() => writeStream.AsStreamForWrite()).Result) { try { serializer.Serialize(outStream, Obj); } catch (InvalidOperationException ex) { throw new TypeNotSerializableException(typeof(T), ex); } await outStream.FlushAsync(); } } 

Thus, you find a serialization problem and can clearly inform the consumer of the API that they have provided an invalid / non-serializable object. That way, if you have an exception that will be passed as part of your I / O, it will become more clear where the problem is. In fact, you can separate the serialization / deserialization aspects into their own discrete method / class so that you can feed on other serializers (or be more clear from the stack trace where the problem is, or just get your methods to do this thing and only one thing). But in any case, rewriting / refactoring really remains to revise the code and does not really matter for the question.

FYI, I also put a null check for your input object, because if the user passes null, they will think that the save was successful when nothing really happened, and they can expect the value to be available for download later when does not exist. If you want to allow nulls as valid values, then don’t worry when checking for an error.

+4
source

It depends on what it means "can be serialized." Any class can be serialized using the XmlSerializer . If what you mean can be serialized, so that the error does not occur, then you will have to try and catch the exceptions in order to say exactly.

+2
source

Source: https://habr.com/ru/post/924586/


All Articles