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
将需要从JsonConverter
inheritance并指定它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
方法中的自定义类型。