Type是接口或抽象类,无法实例化

我将在前言中说我知道问题是什么,我只是不知道如何解决它。 我正在与.NET SOA数据层进行通信,该数据层将数据作为JSON返回。 一种这样的方法返回一个在其中包含多个集合的对象。 该对象基本上如下所示:

{ "Name":"foo", "widgetCollection":[{"name","foo"}, {"name","foo"},], "cogCollection": [{"name","foo"}, {"childCogs",<>},], } 

我的代表这个对象的类看起来像这样:

 public class SuperWidget : IWidget { public string Name { get; set; } public ICollection WidgetCollection { get; set; } public ICollection CogCollection { get; set; } public SuperWidget() { } [JsonConstructor] public SuperWidget(IEnumerable widgets, IEnumerable cogs) { WidgetCollection = new Collection(); CogCollection = new Collection(); foreach (var w in widgets) { WidgetCollection.Add(w); } foreach (var c in cogs) { CogCollection.Add(c); } } } 

这个构造函数工作正常,直到cogCollection添加了一个子集合,现在我收到了上述错误。 具体的cog类看起来像这样:

 [Serializable] public class Cog : ICog { public string name { get; set; } public ICollection childCogs { get; set; } } 

我不想将集合更改为具体类型,因为我使用的是IoC。 因为我正在使用IoC,我真的想摆脱需要使用具体参数的JsonConstructors,但我还没有找到办法做到这一点。 任何建议将不胜感激!

更新:

Yuval Itzchakov建议这个问题可能是重复的,这似乎有点真实(似乎)。 在引用的post中,页面中的一个答案提供了此处提供的相同解决方案。 我没有注意到这个答案,因为OP的问题与我在这里的问题不同。 我的错。

——-我的解决方案——–

正如我所说:Matt的解决方案需要一些工作,但我得到了适合我的设置。 关于他最初的解决方案我不喜欢的一件事就是这样的线条:

  return objectType == typeof(ICog); 

遵循这种模式,您需要为通过线路接收的每种抽象类型都有一个JsonConverter。 这在我的情况下不太理想,所以我创建了一个通用的JsonConverter:

 public class GenericJsonConverter: JsonConverter, IBaseJsonConverter { private readonly IUnityContainer Container; public TalonJsonConverter(IUnityContainer container) { Container = container; } public override bool CanConvert(Type objectType) { return objectType == typeof(T); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var target = serializer.Deserialize(reader); var result = Container.Resolve(); serializer.Populate(target.CreateReader(), result); return result; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { serializer.Serialize(writer, value); } } 

然后就在我反序列化数据之前,我做了类似这样的事情:

  var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; settings.Converters.Add((JsonConverter)Container.Resolve<IBaseJsonConverter>()); 

Protip:如果你使用Resharper,(JsonConverter)会在这种情况下给你一个可疑的投射警告。

希望其他人在路上发现这个有用!

您需要为Json.Net提供自定义序列化程序,以告诉它如何处理子嵌入。 例如:

 var settings = new JsonSerializerSettings(); settings.Converters.Add(new CogConverter()); 

您的CogConverter将需要从JsonConverterinheritance并指定它CanConvert您的ICog接口。 也许是这样的:

 public class CogConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(ICog); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { return serializer.Deserialize(reader, typeof(Cog)); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { serializer.Serialize(writer, value); } } 

在这种情况下,我建议您在IoC容器中注册JsonSerializerSettings 。 如果序列化程序不能负责实际构建Cog本身,您可能还需要考虑让CogConverter访问容器; 这一切都取决于您的特定架构。

编辑

在进一步阅读时,您似乎可能正在寻找具体如何使用IoC创建的ICog用于人口。 我正在使用以下内容作为我的ReadJson的一部分:

 var target = serializer.Deserialize(reader); var objectType = DetermineConcreteType(target); var result = iocContainer.Resolve(objectType); serializer.Populate(target.CreateReader(), result); return result; 

这允许您使用任何对象并从原始JSON填充它,使用您希望在DetermineConcreteType方法中的自定义类型。