Small intro to explain the context:
On Server side:
- I have an assembly "TheoreticalObjects"
- this assembly contains a base class "BaseClass" from which all my THEORETICAL objects are derivating
- the classes inheriting from TheoreticalObjects.BaseClass are for example: TheoreticalObjects.Tube, TheoreticalObjects.Flange, TheoreticalObjects.Caps...
On Client side:
- I have also that assembly for theoretical objects
- but I have an other assembly (dedicated to generate vertices) called "RealObjects"
- this assembly contains a base class "BaseClass" from which all my REAL objects are derivating
- the classes inheriting from RealObjects.BaseClass are for example: RealObjects.Tube, RealObjects.Flange, RealObjects.Caps...
I want to serialize my objects on the server (as TheoreticalObjects.BaseClass), send the json by tcp to the client, and deserialize the json (as RealObjects.BaseClass).
Here are my classes: (Let's suppose that we want to create a Tube):
// my TheoreticalObjects.BaseClass
namespace TheoreticalObjects
{
    [DataContract]
    public class BaseClass
    {
        [DataMember]
        public Guid GUID { get; set; }
        [DataMember]
        public int ID { get; set; }
        [DataMember]
        public string Designation { get; set; }
        [DataMember]
        public string Product { get; set; }
        [DataMember]
        public int IDMaterial { get; set; }
        [DataMember]
        public int Quantity { get; set; }
        [DataMember]
        public string Form { get; set; }
        protected BaseClass()
        { }
        protected BaseClass(int iD, string designation, string product, int iDMaterial, int quantity, string form) 
        {
            ID = iD;
            Designation = designation;
            Product = product;
            IDMaterial = iDMaterial;
            Quantity = quantity;
            Form = form;
        }
    }
}
// my TheoreticalObjects.Tube
namespace TheoreticalObjects
{
    [DataContract]
    public class Tube : BaseClass
    {
        [DataMember]
        public Length Diameter { get; set; }
        [DataMember]
        public Length WallThickness { get; set; }
        [DataMember]
        public Length Length { get; set; }
        public Tube() : base()
        { }
        public Tube(int iD, string designation, string product, int iDmaterial, int quantity, string form, Length diameter, Length Wallthickness, Length length)  : base(iD, designation, product, iDmaterial, quantity,form)
        {
            WallThickness = Wallthickness;
            Diameter = diameter;
            Length = length;
        }
    }
}
// my RealObjects.BaseClass
namespace RealObjects
{
    public class BaseClass
    {
        public Guid GUID { get; set; }
        public int ID { get; set; }
        public string Designation { get; set; }
        public string Product { get; set; }
        public int IDMaterial { get; set; }
        public int Quantity { get; set; }
        public string Form { get; set; }
        protected BaseClass() { }
        protected BaseClass(int iD, string designation, string product, int iDMaterial, int quantity, string form)
        {
            ID = iD;
            Designation = designation;
            Product = product;
            IDMaterial = iDMaterial;
            Quantity = quantity;
            Form = form;
        }
        public List<Face> myFaces = new List<Face>(); // faces of the mesh
        public MyMesh mesh = new MyMesh();
        public void Triangulation(TopoDS_Shape shape, double deflection)
        {
            // things ...
        myFaces = things...
            mesh = new MyMesh(myFaces);
        }
    }
}
// my RealObjects.Tube
namespace RealObjects
{
    public class Tube: BaseClass
    {
        public double diameter;
        public double Wallthickness;
        public double length;
        public Tube() : base() { }
        public Tube(int iD, string designation, string product, int iDmaterial, int quantity, string form, double diameter, double wallThickness, double length) : base(iD, designation, product, iDmaterial, quantity, form)
        {
            this.diameter = diameter;
            this.Wallthickness = wallThickness;
            this.length = length;
            Build(diameter, Wallthickness, length);
        }
        public void Build(double diameter, double Wallthickness, double length)
        {
           //things ...
           Triangulation(things...);
        }
    }
}
My problem is that after serializing and sending my Tube to the client, it doesn't deserialize correctly: I get a RealObjects.BaseClass instead of a RealObjects.BaseClass.Tube.
- I did a Binder to bind names to types, but BindToType() isn't getting called at all when deserializing
_______________On server side____________
//creating the Tube  
TheoreticalObjects.Tube c = new TheoreticalObjects.Tube(1, "Tube", "Element", 1, 1, "tube", new Length(1, UnitsNet.Units.LengthUnit.Meter), new Length(0.1, UnitsNet.Units.LengthUnit.Meter), new Length(2, UnitsNet.Units.LengthUnit.Meter));
// settings for the serializer
JsonSerializerSettings _jsonSerializerSettingsOCCServer = new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented };
_jsonSerializerSettingsOCCServer.Converters.Add(new UnitsNetJsonConverter());
// serialization
string json = JsonConvert.SerializeObject(c, _jsonSerializerSettingsOCCServer).Replace("\r\n", "\n");
// the message that the server will send
CommunicateElement messageObject = new CommunicateElement(NetworkComms.NetworkIdentifier, json, 1234, c.Designation);
after that the message is sent
_______________On client side____________
the message is handled, a function put the message in a "constructionQueue"
// settings for the deserializer
_jsonSerializerSettingsOCC = new JsonSerializerSettings {
            TypeNameHandling = TypeNameHandling.All,
            Binder = new MyBinder(),
            NullValueHandling = NullValueHandling.Ignore,
            DefaultValueHandling = DefaultValueHandling.Ignore,
            Formatting = Newtonsoft.Json.Formatting.Indented,
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };
_jsonSerializerSettingsOCC.Converters.Add(new UnitsNetJsonConverter());
// deserialize the json (that was previously a TheoreticalObjects.Tube) into a RealObjects.BaseClass and add it to the construction queue
constructionQueue.Add(JsonConvert.DeserializeObject<RealObjects.BaseClass>(messageObject.Message, _jsonSerializerSettingsOCC));
...... ...... once it is in the construction queue, I try creating it ..... ...... no need to know what happens after that ..... ...... note that i'm looking for a RealObjects.Tube and not a RealObjects.BaseClass ..... ......
_______________ MyBinder ____________
public class MyBinder : SerializationBinder
    {
        readonly Dictionary<Type, string> typeToName = new Dictionary<Type, string>();
        readonly Dictionary<string, Type> nameToType = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
        public MyBinder()
        {
            List<Type> myTypes = new List<Type>();
            Assembly[] myAssemblies = AppDomain.CurrentDomain.GetAssemblies();
            for (int i = 0; i < myAssemblies.Length; i++)
            {
                if (myAssemblies[i].GetName().Name == "RealObjects")
                {
                    foreach (Type t in myAssemblies[i].GetTypes())
                    {
                        if (t.IsSubclassOf(typeof(RealObjects.BaseClass)))
                        {
                            myTypes.Add(t);
                        }
                    }
                    break;
                }
            }
            foreach (var type in myTypes)
            {
                Map(type, type.Name);
            }
        }
        public void Map(Type type, string name)
        {
            this.typeToName.Add(type, name);
            this.nameToType.Add(name, type);
        }
        public Type Get(string typeName)
        {
            return nameToType[typeName];
        }
        public string Get(Type type)
        {
            return typeToName[type];
        }
        public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
        {
            // we retrieve the name in the RealObjects assembly
            typeName = Get(serializedType);
            assemblyName = "RealObjects";
        }
        public override Type BindToType(string assemblyName, string typeName)
        {
            return Get(typeName);
        }
    } // credit: https://stackoverflow.com/questions/11099466/using-a-custom-type-discriminator-to-tell-json-net-which-type-of-a-class-hierarc
I wasn't able to call the constructor because my RealObjects.BaseClass doesn't have the fields Diameter, wallThickness and Length that my RealObjects.Tube does have, and I loose their values when deserializing to RealObjects.BaseClass
// called after being added to the construction queue
private void CreateObject(RealObjects.BaseClass c)
    {
        MyBinder binder = new MyBinder();
        Type type = binder.BindToType("RealObjects", c.Designation); 
        ConstructorInfo[] ctor = type.GetConstructors();
        BasicClass be;
        foreach (ConstructorInfo ci in ctor)
        {
            try
            {
                object instance = ci.Invoke(new object[] { c });
                be = (BasicClass )instance;
            } catch (Exception e)
            {
                Debug.Log(e.ToString());
            }
        }
        // things...
    }
All suggestions are open
I hope my english wasn't too bad, and that I explained myself clearly, thank you for any help
 
    