【问题标题】:Get a generic type from JSON in WebAPI从 WebAPI 中的 JSON 获取泛型类型
【发布时间】:2016-08-19 17:43:59
【问题描述】:

我想创建一个 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 数据并将其动态转换为适当的类。

【问题讨论】:

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


    【解决方案1】:

    当您以这种方式使用泛型时,必须在编译时知道类型。如果您尝试使用 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; }
    }
    

    【讨论】:

      【解决方案2】:

      试试这样的:

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

      它应该工作。

      【讨论】:

      • 这可以/不会编译。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多