C# 将派生类型较多的泛型对象分配/反序列化为派生类型较少的泛型对象
我有一个具有以下结构的类C# 将派生类型较多的泛型对象分配/反序列化为派生类型较少的泛型对象,c#,generics,json.net,covariance,C#,Generics,Json.net,Covariance,我有一个具有以下结构的类 public class GenericEntity<T> where T : BaseClass { T Property {get; set;} } 公共类泛型实体 其中T:BaseClass { T属性{get;set;} } 我有几个BaseClass的具体实现,并且正在使用这些具体实现来实例化GenericEntity类型的对象 e、 g.var entity=new GenericEntity() 通过将对象序列化为JSON(
public class GenericEntity<T>
where T : BaseClass
{
T Property {get; set;}
}
公共类泛型实体
其中T:BaseClass
{
T属性{get;set;}
}
我有几个BaseClass
的具体实现,并且正在使用这些具体实现来实例化GenericEntity类型的对象
e、 g.var entity=new GenericEntity()
通过将对象序列化为JSON(使用Newtonsoft),我将该实体推送到消息传递框架中。在另一端,我从消息队列中提取该消息(JSON),并尝试使用JsonSerializerSettingsTypeNameHandling.All将消息反序列化为类型GenericEntity
。但在反序列化时,它会抛出带有详细信息的JsonSerializationException
JSON“NewtonSoftPlayed.GenericEntity1[[NewtonSoftPlayed.DerivedClass,NewtonSoftPlayed,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null]],NewtonSoftPlayed,Version=1.0.0,Culture=neutral,PublicKeyToken=null]中指定的类型与“NewtonSoftPlayed.GenericEntity”不兼容[[NewtonSoftPlayed.BaseClass,NewtonSoftPlayed,版本=1.0.0.0,区域性=中立,PublicKeyToken=null]],NewtonSoftPlayed,版本=1.0.0.0,区域性=中立,PublicKeyToken=null'
我怎样才能做到这一点?或者我应该不使用泛型吗?如果是这样,我将在从队列中提取消息后在任何地方编写类型转换,这是我试图避免的。我重新创建了以下代码:
public class GenericEntity<T> where T : BaseClass
{
public T Property { get; set; }
}
public class BaseClass {
}
class Derived1 : BaseClass
{
public int Age { get; set; }
}
class Derived2 : BaseClass {
public string Name { get; set; }
}
....
static void Main()
{
Derived1 d1 = new Derived1 {Age = 23};
GenericEntity<Derived1> entity = new GenericEntity<Derived1> {Property = d1};
var data = JsonConvert.SerializeObject(entity, new JsonSerializerSettings() {
TypeNameHandling = TypeNameHandling.All
});
var baseEntity = JsonConvert.DeserializeObject(data, typeof(GenericEntity<BaseClass>));
}
公共类泛型实体,其中T:BaseClass
{
公共T属性{get;set;}
}
公共类基类{
}
派生类1:基类
{
公共整数{get;set;}
}
派生类2:基类{
公共字符串名称{get;set;}
}
....
静态void Main()
{
Derived1 d1=新Derived1{Age=23};
GenericEntity实体=新GenericEntity{Property=d1};
var data=JsonConvert.SerializeObject(实体,新的JsonSerializerSettings(){
TypeNameHandling=TypeNameHandling.All
});
var baseEntity=JsonConvert.DeserializeObject(数据,typeof(GenericeEntity));
}
我在反序列化数据时没有发现错误。请告诉我您的上下文以及它们之间的区别
这显然行不通:
BaseClass d1 = new Derived1 {Age = 23};
GenericEntity<BaseClass> entity = new GenericEntity<BaseClass> {Property = d1};
var data = JsonConvert.SerializeObject(entity, new JsonSerializerSettings() {
TypeNameHandling = TypeNameHandling.All
});
var baseEntity = JsonConvert.DeserializeObject<GenericEntity<Derived1>>(data, new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All
});
BaseClass d1=new-Derived1{Age=23};
GenericEntity实体=新GenericEntity{Property=d1};
var data=JsonConvert.SerializeObject(实体,新的JsonSerializerSettings(){
TypeNameHandling=TypeNameHandling.All
});
var baseEntity=JsonConvert.DeserializeObject(数据,新的JsonSerializerSettings()
{
TypeNameHandling=TypeNameHandling.All
});
如果序列化基类,它将不负责序列化专用类所具有的所有额外细节(我的意思是,您希望序列化基类,而这正是您要序列化的内容)
将它们序列化为专用实例是您的工作:也就是说,如果您得到一个基类,并且知道您需要一个Derived1,则将该实例解析为Derived1,然后将其序列化。我找不到任何直接的解决方案来实现这一点。正如@Tamas Ionut所建议的,在反序列化时指定基类不会反序列化属性混凝土等级的混凝土
作为一种变通方法,我创建了一个静态方法,它基本上实例化GenericEntity
,并使用反射复制其中的所有属性
public static GenericEntity<BaseClass> ConvertToBaseEntity(object model)
{
if (model.GetType().GetGenericTypeDefinition() != typeof(GenericEntity<>))
{
throw new ArgumentException(
"Model should be of type GenericEntity<T>.", "model");
}
GenericEntity<BaseClass> baseModel = new GenericEntity<BaseClass>();
foreach (var propertyInfo in model.GetType().GetProperties())
{
baseModel.GetType().GetProperty(propertyInfo.Name).SetValue(baseModel, propertyInfo.GetValue(model));
}
return baseModel;
}
publicstaticgenericentity转换为seentity(对象模型)
{
if(model.GetType().GetGenericTypeDefinition()!=typeof(GenericEntity))
{
抛出新的ArgumentException(
“模型应为GenericEntity类型。”,“模型”);
}
GenericEntity baseModel=新的GenericEntity();
foreach(model.GetType().GetProperties()中的var propertyInfo)
{
baseModel.GetType().GetProperty(propertyInfo.Name).SetValue(baseModel,propertyInfo.GetValue(model));
}
返回基模型;
}
我希望,这对某些人有帮助。Hi@Tamas Ionut,如果您使用TypeNameHandling。序列化时的所有设置都会出错。在您尝试的代码中,它将对象反序列化为基类,但缺少派生类属性值。我试图实现的是,反序列化的实例应为派生类型1
,但是接口应该是基类的类型
。我希望这能进一步澄清。谢谢。我同意你的看法。我只序列化专用类。我序列化的是GenericEntity类型的实例
,但在反序列化时,我希望它是GenericEntity
持有GenericEntity类型的实例
。我正在尝试实现以下目标:`Derived1 d1=new Derived1{Age=23};GenericeEntity=new GenericeEntity{Property=d1};var data=JsonConvert.SerializeObject(entity,new JsonSerializerSettings(){TypeNameHandling=TypeNameHandling.All});var baseEntity=JsonConvert.DeserializeObject(数据,新JsonSerializerSettings(){TypeNameHandling=TypeNameHandling.All})(GenericEntity)
参数引发不兼容的类型异常。我们已经找到了使用反射的解决方法。我将我的解决方案作为答案发布在下面。