Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将派生类型较多的泛型对象分配/反序列化为派生类型较少的泛型对象_C#_Generics_Json.net_Covariance - Fatal编程技术网

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),并尝试使用JsonSerializerSettings
TypeNameHandling.All将消息反序列化为类型
GenericEntity
。但在反序列化时,它会抛出带有详细信息的
JsonSerializationException

JSON“NewtonSoftPlayed.GenericEntity
1[[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)
参数引发不兼容的类型异常。我们已经找到了使用反射的解决方法。我将我的解决方案作为答案发布在下面。