I am trying to understand why the below code is not working as expected; the TypeDescriptor is simply not picking up the custom converter from the attributes. I
We've also observed this behavior in pluggable systems involving loading assemblies from outside the appbase folder.
The root of all evil is a flaw in the TypeDescriptorAttribute implementation.
The attribute has two constructor overloads, one for a plaintext type specification (which is — not unexpectedly — pure magic at runtime) and one for an early-bound typeof() reference. If you use the second path, what could possibly go wrong? Well, actually the attribute only uses the first path. The real and correct runtime type reference is flattened into plaintext, and here there be dragons. So it's no use writing a typeof() — it's always the plaintext-and-magic scenario inside.
The solution? No ideal one, but in our case we were consuming the type conversions within our system only, so we picked the ValueSerializerAttribute instead. Which is basically the WPF's way of doing the same stuff. Its implementation is correct around the typeof() .ctor overload in that it succeeds in preserving the early-bound type identity and always loads the correct type, as written in code.
If you want system (or WinForms) code to use the type converter, this won't help.