代码之家  ›  专栏  ›  技术社区  ›  OldSchool

如何强制c#NewtonSoft反序列化程序使用已创建的对象进行反序列化

  •  1
  • OldSchool  · 技术社区  · 6 年前

    执行时

    JsonConvert.DeserializeObject(value, type);
    

    将为给定对象创建一个新对象 type 用于反序列化。我的要求是使用已创建的对象进行反序列化

    CustomObject obj = new CustomObject(); //passing constructor args
    JsonConvert.DeserializeObject(value, obj);    
    

    但此重载不可用。

    那么,有没有什么解决方法可以让我使用已经创建的对象,而不是通过反序列化器创建新类型。?

    我为什么要这样做?(详图)

    我正在编写一个从JSON到c类的通用映射器。JSON的结构如下所示

      {
        "ActionType" : "LogEvent", //this is actually class name in a specific namespace
        "Settings"   : {
               "FailureRetries" : 4,
               "LogChannel"     : 1234 // log channel id, implementation detail
         }
      }
    

    我在配置映射器中执行的操作如下

    public void IAction GetActionFromConfig(){
    
        dynamic config = configManager.Load<dynamic>(); //loads JSON file.
        string className = config.ActionType; //from config we will get file name.
        Type type = Type.GetType(nameSpaceForConfig + "." + className);
    
        string  settingValue = JsonConvert.SerializeObject(config.Settings);
        object actionObject = JsonConvert.DeserializeObject(settingValue, type);
    
        return (IAction)actionObject; // return the IAction from config.
    }
    

    我的问题是 IAction 实现类在构造函数中可能有一些依赖项(例如 ILogger )默认情况下,反序列化不会初始化构造函数参数。我知道我可以覆盖 JsonConverter 对于构造函数初始化,但在编写通用映射器时,我无法使用自定义 JsonConverter公司 .

    我计划做的是首先创建一个映射 Type (c)# 类型 类)转换为依赖项解决的特定实现。

    其次,我将获得给定操作类型的构造函数(config中给定的类型为 ActionType 参数)

    Type type = Type.GetType(nameSpaceForConfig + "." + className);
    var ctors = typeof(type).GetConstructors();
    var ctor = ctors[0];
    List<Type> constructorArguments = new List<Type();
    foreach (var param in ctor.GetParameters())
    {
         constructorArguments.Add(param.ParameterType);
    }
    

    然后,我将查询在步骤1中创建的词典。获取构造函数的参数。

    最后,我将使用 Activator.CreateInstance() (传递上一步中获得的构造函数依赖项)。

    然后使用此对象进行反序列化,以通过配置文件初始化公共属性。

    所以,这就是为什么我需要在 object 不在 类型 .

    注: 前提条件是每个操作都应该有一个包含所有依赖项的构造函数。

    旁白: configManager.Load<T> 实施

    public T Load<T>() where T : class, new() => Load(typeof(T)) as T;
    public object Load(Type type)
    {
      if (!File.Exists(_configurationFilePath))
        return Activator.CreateInstance(type);
    
      var jsonFile = File.ReadAllText(_configurationFilePath);
    
      return JsonConvert.DeserializeObject(jsonFile, type, JsonSerializerSettings);
    }
    
    1 回复  |  直到 6 年前
        1
  •  4
  •   TylerBrinkley    6 年前

    您应该使用 JsonConvert.PopulateObject 方法来填充现有对象。看见 here .