0

I have a data model in one application that I wish to exchange over TCPIP with another application. I need to use type handling because I want to have a single list of an abstract type containing derived types, as opposed to multiple lists for each derived type. As illustrated here:

This :

public Dictionary<int, Parameter> Parameters { get; set; }

Instead of this:

public Dictionary<int, BooleanParameter> BooleanParameters { get; set; }
public Dictionary<int, AnalogParameter> AnalogParameters { get; set; }
public Dictionary<int, SerialParameter> SerialParameters { get; set; }
public Dictionary<int, CommandTrigger> CommandTriggers { get; set; }

When I serialize using type handling, the namespace and the project name are included, and thus the second application is unable to negotiate the type.

"$type": "NAMESPACE_NAME.MyObjectType, PROJECT_NAME"

How do I tell the deserializer to ignore the namespace and project name? Same object, but different projects / namespace. I could even go so far as to make the namespaces match, but the project name was my stumbling block. It seems clunky to have to re-process the json before passing to deserializer.

One caveat is that I cannot create a class library to share between the two applications. The first application runs on proprietary hardware and the VS2008 environment is sandboxed. No external or user libraries can be referenced. The second application is open and developed in VS2015.

JW Baker
  • 103
  • 10
  • Possible duplicate of [Serialize in one assembly, and de-serialize in another?](https://stackoverflow.com/q/28509591/10263) – Brian Rogers May 26 '17 at 21:33

1 Answers1

1

You may try to implement a custom ISerializationBinder to handle just the types you need:

public class MyCustomSerializationBinder : ISerializationBinder
{
    public Type BindToType(string assemblyName, string typeName)
    {
        switch(typeName)
        {
            case "BooleanParameter":
                return typeof(BooleanParameter);
            case "AnalogParameter":
                return typeof(AnalogParameter);
            case "SerialParameter":
                return typeof(SerialParameter);
            case "CommandTrigger":
                return typeof(CommandTrigger);
        }

        return null;
    }

    public void BindToName(Type serializedType, out string assemblyName, out string typeName)
    {
        assemblyName = null;
        typeName = serializedType.Name;
    }
}

And using it inside JsonSerializerSettings:

var obj = JsonConvert.DeserializeObject(json, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Objects,
    SerializationBinder = new MyCustomSerializationBinder()
});
Federico Dipuma
  • 17,655
  • 4
  • 39
  • 56
  • This is where I run into a sandbox issue. It appears that only a compact version of the library is available. The ISerializationBinder interface does not exist, there is a SerializationBinder abstract class but it does not contain a BindToName method, only BindToType. When I use that, it still generates the namespace and project names in the json, and using the implementation you provided on the other application side, it cannot resolve the fully qualified type that is provided. – JW Baker May 26 '17 at 19:55
  • I'm going to accept this answer as it mostly answers the question and gets me what I need with the exception that the sandbox is preventing me from implementing this in whole. However temporarily I can make it work by replacing the namespace and project names in the json before deserialization, until I can find a more elegant solution to that part. – JW Baker May 26 '17 at 21:41
  • It's unfortunate that you are unable to use `ISerializationBinder` in your sandboxed environment. I believe your workaround to replace namespaces is a good choice. I will update the answer if I find a better approach. – Federico Dipuma May 26 '17 at 22:50