从WebAPI中的JSON获取泛型类型

时间:2016-08-19 17:44:00

标签: c# json asp.net-web-api

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

到目前为止,我有这样的事情:

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数据并将其动态转换为适当的类。

2 个答案:

答案 0 :(得分:0)

尝试这样的事情:

var myType = Type.GetType(typeName);
var template = typeof(OutgoingEnvelope<>);
var typeToSet = template.MakeGenericType(myType);

var fromJsonString = JsonConvert.DeserializeObject<OutgoingEnvelope<typeToSet>>(jsonData);

它应该有用。

答案 1 :(得分:0)

以这种方式使用泛型时,必须在编译时知道类型。如果你试图使用var instance = new myType();创建一个新的myType实例,它会是类似的,这也不会因为相同的原因(或多或少)而编译。

JsonConvert上的反序列化器(请参阅DeserializeObject)提供了一个非泛型版本,如果您愿意,可以稍后再投射。这有一些要求。

  • 您必须为容器和可选的泛型类型参数
  • 定义接口
  • 通用接口参数必须标记为covariant(out keyword)

这是一个执行的自包含示例,唯一缺少的是从字符串中获取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; }
}