c#如何从Json字符串到类实例然后调用方法

时间:2018-02-07 11:41:32

标签: c# json reflection json-deserialization

我有一个包含这些条目的(sql)表:

表:

Type (varchar)     Json (varchar)
MyClassA           { "Id": 1, "Name": "OneName" }   
MyClassB           { "Id": 2, "Name": "TwoName" }

我需要调用ClassA和/或ClassB中的方法来更改Name属性。

类似下一个代码:

public void Test(string type, string json)
{
   Type type = Type.GetType($"MyNamespace.a.b.{type}, MyDll");

   // Some code here....
   // - Casting to IData    ??
   // - var obj = JsonConvert.DeserializeObject(json);       ??
   // - var obj = JsonConectt.DeserializeObject<type>(json)  ??
   // - var x = Convert.Change(...) ??


   instance.DoSomething("bazinga");

}


public interface IData 
{
   void DoSomething();
}

public class MyClassA : IData
{
   public int Id {get; set;}
   public string Name {get; set;}

   public void DoSomething(string newName)
   {
       Name = newName;
   }
}

public class MyClassB : IData
{
   public int Id {get; set;}
   public string Name {get; set;}

   public void DoSomething(string newName)
   {
       name = $"{Id}, {newName}";
   }
}

尝试A:

var obj = JsonConvert.DeserializeObject(json);
var ins = obj as IData;
// ins = null

尝试B:

dynamic obj = JsonConvert.DeserializeObject<dynamic>(json);
// failed

尝试C:

var obj = JsonConvert.DeseriallizeObject<type>(json);
// Not allowed to use 'type' in this way.

2 个答案:

答案 0 :(得分:2)

您可以执行以下操作:

var instance = JsonConvert.DeserializeObject(json, type) as IData;

有关官方文档,请参阅HERE。第二个参数将定义要反序列化的类型。

答案 1 :(得分:0)

因此,首先,您必须为每个通用调用创建一个专用类型,通常在运行时完成。你需要做的就是自己创建这种类型是使用一些反思:

public void Test(string type, string json)
{
    Type type = Type.GetType($"MyNamespace.a.b.{type}, MyDll");
    // from all method named "DeserializeObject"
    // find the one that is generic method
    MethodInfo deserializeObjectMethodInfo = typeof(JsonConvert)
        .GetMethods(BindingFlags.Static | BindingFlags.Public)
        .FirstOrDefault(m => m.IsGenericMethod && m.Name == "DeserializeObject");
    // create a specialized method for the requested type
    // same as you would call DeserializeObject<type>
    MethodInfo specializedDeserializeObject = deserializeObjectMethodInfo.MakeGenericMethod(type);
    // invoke that method with json as parameter
    // and cast it to IData
    IData data = (IData)specializedDeserializeObject.Invoke(null, json);
    // do whatever you want with the deserialized object
    data.DoSomething("bazinga");
}