Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何序列化3种对象类型中的任何一种,其中一种包含抽象类?_C#_.net_Json.net - Fatal编程技术网

C# 如何序列化3种对象类型中的任何一种,其中一种包含抽象类?

C# 如何序列化3种对象类型中的任何一种,其中一种包含抽象类?,c#,.net,json.net,C#,.net,Json.net,我正在通过网络发送3个.net对象: - List<int> - List<ParentObject> - string 我想根据接收到的3个对象调用3个不同的函数 Object genericObject = JsonConvert.DeserializeObject(message, new JsonSerializerSettings { TypeNameHandling = TypeNameHandl

我正在通过网络发送3个.net对象:

 - List<int>
 - List<ParentObject>
 - string
我想根据接收到的3个对象调用3个不同的函数

Object genericObject = JsonConvert.DeserializeObject(message, new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Auto
            });

        if (genericObject is List<int>)
        {
          List<int> myList= (List<int>)genericObject;
          myfunction1(myList);
        }
        if (genericObject is List<ParentObject>)
        {
         //etc..
Object genericObject=JsonConvert.DeserializeObject(消息,新的JsonSerializerSettings
{
TypeNameHandling=TypeNameHandling.Auto
});
如果(genericObject是列表)
{
列表myList=(列表)genericObject;
myfunction1(myList);
}
如果(genericObject是列表)
{
//等等。。
ParentObject导致DeserializeObject()出现问题,因为它说“无法创建ParentObject类型的实例。type是接口或抽象类,无法实例化”。因此我想我可能需要在

这仍然不能解决我的问题,因为CustomCreationConverter在反序列化期间需要类型,而我在反序列化之后才检查类型


有什么解决问题的建议吗?

如果我使用这样定义的对象:

public enum EntityType { Child1, Child2 };

abstract class ParentObject
{
    public EntityType et { get; set; }
}

class ChildClass : ParentObject
{
    public int ChildClassProp { get; set; }

    public ChildClass()
    {
        this.et = EntityType.Child1;
    }
}

class ChildClass2 : ParentObject
{
    public int ChildClass2Prop { get; set; }

    public ChildClass2()
    {
        this.et = EntityType.Child2;
    }
}
JsonSerializerSettings JSsettings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Objects
};

List<ParentObject> list = new List<ParentObject>();
list.Add(new ChildClass() { ChildClassProp = 1 });
list.Add(new ChildClass2() { ChildClass2Prop = 2 });

string message = JsonConvert.SerializeObject(list,
      Newtonsoft.Json.Formatting.Indented, JSsettings);

list = JsonConvert.DeserializeObject<List<ParentObject>>(message, JSsettings);
[
  {
    "$type": "ConsoleApplication4.ChildClass, ConsoleApplication4",
    "ChildClassProp": 1,
    "et": 0
  },
  {
    "$type": "ConsoleApplication4.ChildClass2, ConsoleApplication4",
    "ChildClass2Prop": 2,
    "et": 1
  }
]   
{
  "$type": "System.Collections.Generic.List`1[[ConsoleApplication4.ParentObject, ConsoleApplication4]], mscorlib",
  "$values": [
    {
      "ChildClassProp": 1,
      "et": 0
    },
    {
      "ChildClass2Prop": 2,
      "et": 1
    }
  ]
}
然后我可以愉快地将派生类(
ChildClass
ChildClass2
)反序列化为
ParentObject
,如下所示:

public enum EntityType { Child1, Child2 };

abstract class ParentObject
{
    public EntityType et { get; set; }
}

class ChildClass : ParentObject
{
    public int ChildClassProp { get; set; }

    public ChildClass()
    {
        this.et = EntityType.Child1;
    }
}

class ChildClass2 : ParentObject
{
    public int ChildClass2Prop { get; set; }

    public ChildClass2()
    {
        this.et = EntityType.Child2;
    }
}
JsonSerializerSettings JSsettings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Objects
};

List<ParentObject> list = new List<ParentObject>();
list.Add(new ChildClass() { ChildClassProp = 1 });
list.Add(new ChildClass2() { ChildClass2Prop = 2 });

string message = JsonConvert.SerializeObject(list,
      Newtonsoft.Json.Formatting.Indented, JSsettings);

list = JsonConvert.DeserializeObject<List<ParentObject>>(message, JSsettings);
[
  {
    "$type": "ConsoleApplication4.ChildClass, ConsoleApplication4",
    "ChildClassProp": 1,
    "et": 0
  },
  {
    "$type": "ConsoleApplication4.ChildClass2, ConsoleApplication4",
    "ChildClass2Prop": 2,
    "et": 1
  }
]   
{
  "$type": "System.Collections.Generic.List`1[[ConsoleApplication4.ParentObject, ConsoleApplication4]], mscorlib",
  "$values": [
    {
      "ChildClassProp": 1,
      "et": 0
    },
    {
      "ChildClass2Prop": 2,
      "et": 1
    }
  ]
}
其中的关键是使用
typenameholling=typenameholling.Auto
进行序列化和反序列化。使用
typenameholling.Arrays
创建如下消息:

public enum EntityType { Child1, Child2 };

abstract class ParentObject
{
    public EntityType et { get; set; }
}

class ChildClass : ParentObject
{
    public int ChildClassProp { get; set; }

    public ChildClass()
    {
        this.et = EntityType.Child1;
    }
}

class ChildClass2 : ParentObject
{
    public int ChildClass2Prop { get; set; }

    public ChildClass2()
    {
        this.et = EntityType.Child2;
    }
}
JsonSerializerSettings JSsettings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Objects
};

List<ParentObject> list = new List<ParentObject>();
list.Add(new ChildClass() { ChildClassProp = 1 });
list.Add(new ChildClass2() { ChildClass2Prop = 2 });

string message = JsonConvert.SerializeObject(list,
      Newtonsoft.Json.Formatting.Indented, JSsettings);

list = JsonConvert.DeserializeObject<List<ParentObject>>(message, JSsettings);
[
  {
    "$type": "ConsoleApplication4.ChildClass, ConsoleApplication4",
    "ChildClassProp": 1,
    "et": 0
  },
  {
    "$type": "ConsoleApplication4.ChildClass2, ConsoleApplication4",
    "ChildClass2Prop": 2,
    "et": 1
  }
]   
{
  "$type": "System.Collections.Generic.List`1[[ConsoleApplication4.ParentObject, ConsoleApplication4]], mscorlib",
  "$values": [
    {
      "ChildClassProp": 1,
      "et": 0
    },
    {
      "ChildClass2Prop": 2,
      "et": 1
    }
  ]
}
请注意,列表项的类型不包括在内,只包括列表的类型,因此会出现错误

编辑:

我认为最简单的方法就是定义一个简单的类,像这样的类,作为序列化对象的薄包装器:

class ObjectContainer
{
    public object Data { get; set; }
}
然后代码将如下所示(注意对
typenameholling.Auto
的更改):

JsonSerializerSettings JSsettings=新的JsonSerializerSettings
{
TypeNameHandling=TypeNameHandling.Auto
};
列表=新列表();
添加(new ChildClass(){ChildClassProp=1});
添加(新的ChildClass2(){ChildClass2Prop=2});
ObjectContainer=newObjectContainer()
{
数据=列表
};
string message=JsonConvert.SerializeObject(容器,
Newtonsoft.Json.Formatting.Indented,JSsettings);
var objectContainer=JsonConvert.DeserializeObject(消息,JSsettings);
if(objectContainer.Data为列表)
{
Write(“objectContainer.Data是List”);
}
else if(objectContainer.Data为列表)
{
Write(“objectContainer.Data是List”);
}
else if(objectContainer.Data为字符串)
{
Write(“objectContainer.Data是字符串”);
}

我采用这种方法的原因是,Json.Net将负责几乎所有的工作。只需调用非泛型的
JsonConvert.DeserializeObject
方法就可以了,但是您需要做额外的工作,因为该方法返回的是
JContainer
,而不是
对象
,我不能使用
行列表=JsonConvert.DeserializeObject(message,JSsettings);
因为我不知道将接收3种对象类型中的哪一种。我必须在不知道类型的情况下进行反序列化,然后在中检查该类型。否则,将其转换为该类型并调用相应的函数。