![](/img/trans.png)
[英]Could not create an instance of type . Type is an interface or abstract class and cannot be instantiated
[英]Type is an interface or abstract class and cannot be instantiated
我先說我知道問題是什么,我只是不知道如何解決它。 我正在與以 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>>());
提示:如果你使用 Resharper,(JsonConverter) 會在這種情況下給你一個可疑的轉換警告。
希望其他人發現這很有用!
您需要向 Json.Net 提供自定義序列化程序,以告訴它如何處理子齒輪。 例如:
var settings = new JsonSerializerSettings();
settings.Converters.Add(new CogConverter());
您的CogConverter
將需要從JsonConverter
繼承並指定它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);
}
}
在這種情況下,我建議將您的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
混凝土類型方法中使用您希望的自定義類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.