介绍内容的小介绍:
在服务器端:
在客户端:
我想序列化服务器上的对象(作为TheoreticalObjects.BaseClass),通过tcp将json发送到客户端,然后反序列化json(作为RealObjects.BaseClass)。
这是我的课程:(假设我们要创建一个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...);
}
}
}
我的问题是,在将我的Tube序列化并发送给客户端之后,它无法正确反序列化:我得到的是RealObjects.BaseClass而不是RealObjects.BaseClass.Tube。
_______________在服务器端____________
//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);
在发送邮件之后
_______________在客户端______________
消息已处理,函数将消息放入“ 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));
...... ......一旦进入施工队列,我尝试创建它..... ......无需知道之后会发生什么..... ......请注意,我在寻找RealObjects.Tube,而不是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
我无法调用构造函数,因为RealObjects.BaseClass没有RealObjects.Tube拥有的Diameter,wallThickness和Length字段,并且在反序列化为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...
}
所有建议均已公开
我希望我的英语还不错,并且我已经清楚地解释了自己,谢谢您的帮助
答案 0 :(得分:1)
难题的缺失部分是序列化方式,该序列化方式缺少“根对象的多态类型信息”,需要如this answer所示将其添加到 Serializing an interface/abstract object using NewtonSoft.JSON 通过dbc:
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));
JsonSerializerSettings _jsonSerializerSettingsOCCServer = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, Formatting = Newtonsoft.Json.Formatting.Indented };
_jsonSerializerSettingsOCCServer.Converters.Add(new UnitsNetJsonConverter());
string json = JsonConvert.SerializeObject(c, typeof(TheoreticalObjects.BaseClass), _jsonSerializerSettingsOCCServer);
反序列化部分的设置与我的第一篇文章相同。 但是活页夹的构造函数会发生变化:
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, "TheoreticalObjects."+type.Name); //this part changed
}
}
以这种方式绑定到正确的类(RealObjects.Tube)
我的构造队列中有一个RealObjects.Tube类的实例
请注意,我必须将RealObjects.Tube中的字段修改为Length类型,而不是double类型