C# 从WebAPI中的JSON获取泛型类型

C# 从WebAPI中的JSON获取泛型类型,c#,json,asp.net-web-api,C#,Json,Asp.net Web Api,我想创建一个Web Api方法,该方法将接受JSON和一个带有类型名称的字符串 到目前为止,我有这样的想法: public void Write(string typeName, string jsonData) { var myType = Type.GetType(typeName); var fromJsonString = JsonConvert.DeserializeObject<OutgoingEnvelope<myType>>(jsonDat

我想创建一个Web Api方法,该方法将接受JSON和一个带有类型名称的字符串

到目前为止,我有这样的想法:

public void Write(string typeName, string jsonData)
{
    var myType = Type.GetType(typeName);
    var fromJsonString = JsonConvert.DeserializeObject<OutgoingEnvelope<myType>>(jsonData);
}
var myType = Type.GetType(typeName);
var template = typeof(OutgoingEnvelope<>);
var typeToSet = template.MakeGenericType(myType);

var fromJsonString = JsonConvert.DeserializeObject<OutgoingEnvelope<typeToSet>>(jsonData);
public void Write(字符串typeName,字符串jsonData)
{
var myType=Type.GetType(typeName);
var fromJsonString=JsonConvert.DeserializeObject(jsonData);
}
支出坡度的定义如下:

public class OutgoingEnvelope<T>
{
    public string TypeId { get; set; }

    public OutgoingEnvelope()
    {
        Documents = new List<T>();
    }

    public List<T> Documents { get; set; }
}
public class OutgoingEnvelope
{
公共字符串TypeId{get;set;}
公共开支斜坡()
{
文件=新列表();
}
公共列表文档{get;set;}
}
目前我得到的信息是:

“myType”是一个变量,但与类型一样使用


我们的最终目标是能够获取JSON数据并将其动态转换为适当的类。

尝试以下方法:

public void Write(string typeName, string jsonData)
{
    var myType = Type.GetType(typeName);
    var fromJsonString = JsonConvert.DeserializeObject<OutgoingEnvelope<myType>>(jsonData);
}
var myType = Type.GetType(typeName);
var template = typeof(OutgoingEnvelope<>);
var typeToSet = template.MakeGenericType(myType);

var fromJsonString = JsonConvert.DeserializeObject<OutgoingEnvelope<typeToSet>>(jsonData);
var myType=Type.GetType(typeName);
var模板=类型(支出坡度);
var typeToSet=template.MakeGenericType(myType);
var fromJsonString=JsonConvert.DeserializeObject(jsonData);

它应该会起作用

以这种方式使用泛型时,类型必须在编译时已知。如果您尝试使用
var instance=new myType()创建一个myType的新实例,则情况类似,出于同样的原因(或多或少),这也不会编译

JsonConvert上的反序列化程序(请参阅)提供了一个非通用版本,如果需要,您可以稍后强制转换该版本。不过,这有一些要求

  • 您必须为容器定义一个接口,还可以选择泛型类型参数
  • 通用接口参数必须标记为协变(out关键字)
这是一个自包含的执行示例,唯一缺少的是从字符串中获取
类型,而不是硬编码

public class SomeController {
    public void Write()
    {   
        var objectToSerialize = new OutgoingEnvelope<SomeDocument>()    
        {   
            Documents = new List<SomeDocument>() {new SomeDocument() {Name = "Hi"}},    
            TypeId = "Some type"    
        };
        var json = JsonConvert.SerializeObject(objectToSerialize);

        // var myType = Type.GetType(typeName); 
        var myType = typeof(OutgoingEnvelope<SomeDocument>);    
        var fromJsonString = JsonConvert.DeserializeObject(json, myType) as IOutgoingEnvelope<IDocumentType>;   

        if(fromJsonString == null)  
            throw new NullReferenceException(); 
    }   
}

public interface IDocumentType
{
    string Name { get; set; }
    // known common members in the interface
}

public class SomeDocument : IDocumentType
{
    public string Name { get; set; }
}

public interface IOutgoingEnvelope<T> where T : IDocumentType
{
    string TypeId { get; set; }
    IEnumerable<T> Documents { get; }
}

public class OutgoingEnvelope<T> : IOutgoingEnvelope<T> where T : IDocumentType
{
    public string TypeId { get; set; }

    public OutgoingEnvelope()
    {
        Documents = new List<T>();
    }

    public IEnumerable<T> Documents { get; set; }
}
公共类控制器{
公共空写()
{   
var objectToSerialize=new OutgoingEnvelope()
{   
Documents=new List(){new SomeDocument(){Name=“Hi”},
TypeId=“某种类型”
};
var json=JsonConvert.SerializeObject(objectToSerialize);
//var myType=Type.GetType(typeName);
var myType=类型(向外延伸的斜坡);
var fromJsonString=JsonConvert.DeserializeObject(json,myType)作为IOutgoingEnvelope;
if(fromJsonString==null)
抛出新的NullReferenceException();
}   
}
公共接口IDocumentType
{
字符串名称{get;set;}
//接口中的已知公共成员
}
公共类SomeDocument:IDocumentType
{
公共字符串名称{get;set;}
}
公共接口IOutgoingEnvelope,其中T:IDocumentType
{
字符串类型ID{get;set;}
IEnumerable文档{get;}
}
公共类OutgoingEnvelope:IOOutgoingEnvelope其中T:IDocumentType
{
公共字符串TypeId{get;set;}
公共开支斜坡()
{
文件=新列表();
}
公共IEnumerable文档{get;set;}
}

这可以/不会编译。