c# - 类型是接口(interface)或抽象类,不能实例化

我会先说我知道问题出在哪里,只是不知道如何解决它。我正在与以 JSON 形式返回数据的 .NET SOA 数据层进行通信。一种这样的方法返回一个包含多个集合的对象。对象基本上是这样的:

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

代表这个对象的类如下所示:

public class SuperWidget : IWidget
{
    public string Name { get; set; }

    public ICollection<IWidget> WidgetCollection { get; set; }
    public ICollection<ICog> CogCollection { get; set; }

    public SuperWidget()
    {
    }

    [JsonConstructor]
    public SuperWidget(IEnumerable<Widget> widgets, IEnumerable<Cog> cogs)
    {
        WidgetCollection = new Collection<IWidget>();
        CogCollection = new Collection<ICog>();

        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<ICog> childCogs { get; set; }        
}  

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

更新:

Yuval Itzchakov 关于这个问题可能是重复的建议在某种程度上是正确的(似乎)。在引用的帖子中,页面下方的答案之一提供了与此处提供的相同解决方案。我没有注意到那个答案,因为 OP 的问题与我在这里的问题不同。我的错。

-------我的解决方案--------

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

 return objectType == typeof(ICog); 

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

public class GenericJsonConverter<T>: JsonConverter, IBaseJsonConverter<T>
{
    private readonly IUnityContainer Container;
    public GenericJsonConverter(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<Newtonsoft.Json.Linq.JObject>(reader);
        var result = Container.Resolve<T>();
        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<ICog>>());

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

希望其他人在以后发现这很有用!

最佳答案

您需要为 Json.Net 提供一个自定义序列化程序来告诉它如何处理子 cogs。例如:

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

您的 CogConverter 将需要从 JsonConverter 继承并指定它 CanConvert 您的 ICog 接口(interface)。也许是这样的:

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);
    }
}

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

编辑

进一步阅读后,您似乎正在寻找如何专门使用 IoC 创建的 ICog 进行人口。我将以下内容用作我的 ReadJson 的一部分:

var target = serializer.Deserialize<Newtonsoft.Json.Linq.JObject>(reader);
var objectType = DetermineConcreteType(target);
var result = iocContainer.Resolve(objectType);
serializer.Populate(target.CreateReader(), result);
return result;

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

https://stackoverflow.com/questions/24644464/

相关文章:

json - d3 - 读取 JSON 数据而不是 CSV 文件

bash - jq 直接替换文件上的文本(如 sed -i)

javascript - 如何使用 Angular-Translate 显示翻译?

android - 如何使用 Android Lollipop 中的注释在 Android Jack

.net - JSON.NET 教程

mysql - 如何在 MySQL 中编写可以解析列中 JSON 数据的查询?

javascript - Chrome 扩展 "Refused to evaluate a stri

javascript - 日历结束日期错了一天

jquery - 你使用 Ajax JSON 还是 HTML?

json - getJSON 与 optJSON