EF:如何反序列化从抽象 class 继承的对象?
EF: How to deserialize an object inherited from an abstract class?
是否可以反序列化从抽象 Class 继承的对象?
我有以下内容:
public abstract partial class Item
{
public Item() { }
public int ItemID { get; set; }
public Nullable<int> ObjectStateID { get; set; }
}
public abstract partial class Appointment : Item
{
public Appointment() { }
public string AppointmentDescription { get; set; }
}
public partial class AppointedActivity : Appointment
{
public Nullable<int> AppointedActivityID { get; set; }
}
public partial class AppointedDevice : Appointment
{
public Nullable<int> AppointedDeviceID { get; set; }
}
我有一个控制器应该 POST Item
s:
public Item PostItem([FromBody]Item item)
{
// item is always null here.
return item;
}
我遇到的问题是,无论我的主体内容是什么,控制器中的项目始终为空。
发送到控制器的 JSON 示例:
{
"ObjectStateID": 1,
"AppointmentDescription": "test",
"AppointedActivityID": 90902 // Valid Activity ID.
}
我正在使用 Entity Framework,但我不确定该代码有什么问题。
谢谢!
您不能将抽象类型作为默认模型绑定器的参数传递给您的控制器。因为模型绑定器在创建此参数的实例时会出错。
如果您想为此类型创建自己的自定义模型活页夹;
public class ItemModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var values = (ValueProviderCollection) bindingContext.ValueProvider;
var itemId = (int) values.GetValue("ItemId").ConvertTo(typeof (int));
var objectStateId = (int?) values.GetValue("ObjectStateId").ConvertTo(typeof(int));
//Make desicion and create the real type instance Appointment, AppointedActivity or AppointedDevice
return (Item) new Appointment { ItemId= itemId, ObjectStateId = objectStateId };
}
}
在Global.asax;
ModelBinders.Binders.Add(new KeyValuePair<Type, IModelBinder>(typeof(Item), new ItemModelBinder()));
我最终将我的解决方案基于 this and this 并创建了一个使用 ItemResolver
:
的自定义 Contract Resolver
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject item = JObject.Load(reader);
switch ((ResourceKind)item["ResourceKind"].Value<int>())
{
case ResourceKind.ACTIVITY:
return item.ToObject<AppointedActivity>();
case ResourceKind.CONSUMABLE:
return item.ToObject<AppointedConsumable>();
case ResourceKind.DEVICE:
return item.ToObject<AppointedDevice>();
default:
throw new Exception("Invalid ResourceType");
}
}
是否可以反序列化从抽象 Class 继承的对象?
我有以下内容:
public abstract partial class Item
{
public Item() { }
public int ItemID { get; set; }
public Nullable<int> ObjectStateID { get; set; }
}
public abstract partial class Appointment : Item
{
public Appointment() { }
public string AppointmentDescription { get; set; }
}
public partial class AppointedActivity : Appointment
{
public Nullable<int> AppointedActivityID { get; set; }
}
public partial class AppointedDevice : Appointment
{
public Nullable<int> AppointedDeviceID { get; set; }
}
我有一个控制器应该 POST Item
s:
public Item PostItem([FromBody]Item item)
{
// item is always null here.
return item;
}
我遇到的问题是,无论我的主体内容是什么,控制器中的项目始终为空。
发送到控制器的 JSON 示例:
{
"ObjectStateID": 1,
"AppointmentDescription": "test",
"AppointedActivityID": 90902 // Valid Activity ID.
}
我正在使用 Entity Framework,但我不确定该代码有什么问题。
谢谢!
您不能将抽象类型作为默认模型绑定器的参数传递给您的控制器。因为模型绑定器在创建此参数的实例时会出错。
如果您想为此类型创建自己的自定义模型活页夹;
public class ItemModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var values = (ValueProviderCollection) bindingContext.ValueProvider;
var itemId = (int) values.GetValue("ItemId").ConvertTo(typeof (int));
var objectStateId = (int?) values.GetValue("ObjectStateId").ConvertTo(typeof(int));
//Make desicion and create the real type instance Appointment, AppointedActivity or AppointedDevice
return (Item) new Appointment { ItemId= itemId, ObjectStateId = objectStateId };
}
}
在Global.asax;
ModelBinders.Binders.Add(new KeyValuePair<Type, IModelBinder>(typeof(Item), new ItemModelBinder()));
我最终将我的解决方案基于 this and this 并创建了一个使用 ItemResolver
:
Contract Resolver
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject item = JObject.Load(reader);
switch ((ResourceKind)item["ResourceKind"].Value<int>())
{
case ResourceKind.ACTIVITY:
return item.ToObject<AppointedActivity>();
case ResourceKind.CONSUMABLE:
return item.ToObject<AppointedConsumable>();
case ResourceKind.DEVICE:
return item.ToObject<AppointedDevice>();
default:
throw new Exception("Invalid ResourceType");
}
}