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

本文关键字:获取 泛型类型 JSON WebAPI 中的 | 更新日期: 2023-09-27 18:03:20

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

到目前为止,我有这样的东西:

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

OutgoingEnvelope将定义为:

public class OutgoingEnvelope<T>
{
    public string TypeId { get; set; }
    public OutgoingEnvelope()
    {
        Documents = new List<T>();
    }
    public List<T> Documents { get; set; }
}

当前我得到的消息:

'myType'是一个变量,但被当作类型使用。

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

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

以这种方式使用泛型时,必须在编译时知道该类型。如果您尝试使用var instance = new myType();创建myType的新实例,情况也类似,这也会由于相同的原因(或多或少)无法编译。

JsonConvert(参见DeserializeObject)上的反序列化器提供了一个非泛型版本,如果你想的话,你可以稍后强制转换。但这有一些要求。

  • 你必须为你的容器定义一个接口和可选的泛型类型参数
  • 泛型接口参数必须标记为协变(out关键字)

这是一个执行的自包含示例,唯一缺少的是从字符串中获取Type,而不是硬编码。

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 myType = Type.GetType(typeName);
var template = typeof(OutgoingEnvelope<>);
var typeToSet = template.MakeGenericType(myType);
var fromJsonString = JsonConvert.DeserializeObject<OutgoingEnvelope<typeToSet>>(jsonData);

应该可以。