【问题标题】:Could not create an instance of type X. Type is an interface or abstract class and cannot be instantiated无法创建类型 X 的实例。类型是接口或抽象类,无法实例化
【发布时间】:2015-05-20 12:29:52
【问题描述】:

使用版本 7.0.1 Beta3,我正在尝试序列化/反序列化具有抽象类数组属性的复杂 POCO。这些数组可以包含派生自抽象类的实例。

在序列化时,一切似乎都正常。下面的Json片段显示类型信息设置正确。

Json 片段:

 "Items": 
 [
     {
         "$type": "IVXB_TS, ...",
         "inclusive": true,
         "value": "20091231"
     }
 ]

但是反序列化失败并出现以下错误:

无法创建 QTY 类型的实例。类型是接口或抽象类,不能实例化。

类层次结构如下:

[System.Xml.Serialization.XmlIncludeAttribute(typeof(IVXB_TS))]
public abstract partial class ANY : object, System.ComponentModel.INotifyPropertyChanged
{
}

[System.Xml.Serialization.XmlIncludeAttribute(typeof(IVXB_TS))]
public abstract partial class QTY : ANY
{
}

[System.Xml.Serialization.XmlIncludeAttribute(typeof(IVXB_TS))]
public partial class TS : QTY
{
}

public partial class IVXB_TS : TS
{
}

Items 属性:

[System.Xml.Serialization.XmlElementAttribute("high", typeof(IVXB_TS))]
[System.Xml.Serialization.XmlElementAttribute("low", typeof(IVXB_TS))]
public QTY[] Items

Json 片段中的类型信息似乎没有使用。这是反序列化配置问题吗?

【问题讨论】:

    标签: c# json.net


    【解决方案1】:

    解决这个问题的方法是配置反序列化器使用json中的类型信息。默认不使用。

    序列化是这样完成的:

    Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer();
    serializer.Converters.Add(new Newtonsoft.Json.Converters.JavaScriptDateTimeConverter());
    serializer.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
    serializer.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto;
    serializer.Formatting = Newtonsoft.Json.Formatting.Indented;
    
    using (StreamWriter sw = new StreamWriter(fileName))
    using (Newtonsoft.Json.JsonWriter writer = new Newtonsoft.Json.JsonTextWriter(sw))
    {
        serializer.Serialize(writer, obj, typeof(MyDocumentType));
    }
    

    反序列化时,必须设置 TypeNameHandling 的设置:

    MyDocumentType  obj = Newtonsoft.Json.JsonConvert.DeserializeObject<MyDocumentType>(File.ReadAllText(fileName), new Newtonsoft.Json.JsonSerializerSettings 
    { 
        TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto,
        NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,
    });
    

    【讨论】:

    • 这帮助我解决了这个问题。如果您从数据库或外部数据源反序列化,请注意:确保 $type 字段是您的字典/json 字符串中的第一个键。
    【解决方案2】:

    就我而言,将TypeNameHandling 设置为Auto 并不能解决问题,但将其设置为All 可以解决问题。由于TypeNameHandling = TypeNameHandling.All 对我来说似乎有点矫枉过正,我再次选择了Auto,但这一次,我将根对象的类型也传递给了JsonConvert.SerializeObject 函数:

    var settings = new JsonSerializerSettings{ TypeNameHandling = TypeNameHandling.Auto };
    
    var json = JsonConvert.SerializeObject(obj, typeof(ObjType), settings);
    
    var deserializedObj = JsonConvert.DeserializeObject<ObjType>(json, settings);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多