ServiceStack/ServiceStack.Text — pull request #427 by ygormutti (2014-07-28 18:02:07+00:00)
Title: Use public instance method ToJson as RawDeserializeFn if present

Hi!

I needed to customize serialization for generic types without knowing the generic parameters beforehand. `JsConfig` provides no interface to customize serialization for open generic types and it's not possible to use an open generic type as the generic argument for `JsConfig`.

I've tried to solve this issue by setting `JsConfig.RawSerializeFn` (`T` being the generic closed type) from the static constructors of the generic classes, like this:

class Generic
{
static Generic()
{
JsConfig>.RawSerializeFn = ...
}
}

but had issues with SS.Text's serializers cache. One could argue that I should configure SS.Text at the start of the application, before any serialization takes place, but this isn't practical because I don't know the generic parameters beforehand, it could be every possible combination of a lot of types.

I believe this issues were happening because static constructors sometimes were being invoked after instances of related types had already been serialized. I've tried to write a test case to reproduce this issue but was unable to reproduce it in a controlled environment. There seems to be a race condition involving `WriteType.PropertyWriters`.

So I've made the changes you see in this pull request to allow the user to customize serialization by implementing a public `ToJson` instance method that returns a string. This patch passed all the tests and I've added one test case to prove it's working. It works around the cache problem and allow users to customize serialization of open generic types.

I think it's almost backwards-compatible because: if RawSerializeFn is set then `JsConfig` will stick to it, and if there's already a method with this signature the odds are that it was already being used to do the same thing (except obviously in cases where it doesn't return strings).

The biggest drawback I see about this patch is that in order to use it you need to put behavior on classes that most of the time should be POCO's. However, SS.Text already has serialization hooks that involve putting behavior on DTO's (namely the `ShouldSerialize*` methods).

Please, let me know what you think about it.