【发布时间】:2018-04-24 13:18:05
【问题描述】:
在做的时候
JsonConvert.DeserializeObject(value, type);
根据给定的type 创建一个新对象以进行反序列化。我的要求是我想使用已经创建的对象进行反序列化
CustomObject obj = new CustomObject(); //passing constructor args
JsonConvert.DeserializeObject(value, obj);
但是这个重载是不可用的。
那么,有什么解决方法可以让我使用已经创建的对象,而不是通过 Deserializer 创建新类型。
我为什么要这样做? (详细)
我正在编写一个从 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#Type 类)映射到特定实现以进行依赖解析。
其次,我将获取给定操作类型的构造函数(在配置中使用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 而不是 type 上进行反序列化。
注意:前提条件是每个动作都应该有一个包含所有依赖项的构造函数。
旁白: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);
}
【问题讨论】:
-
@Codeman01101001 在调用构造函数时我不能使用特定类型,因为
JsonConvert会像我在通用上下文中那样。
标签: c# json serialization reflection json.net