<T>在给定 T 的字符串表示形式的情况下,如何实例化 SomeObject 的实例?



我们有以下类…

public class ValueHolder<T>
{
    public T Value { get; set; }
    public Type ValueType => typeof(T);
}

…我们当然可以这样实例化。

var foo = new ValueHolder<string>() { Value = "Hello World!" };
var laa = new ValueHolder<int>() { Value = 44 };

当我们使用NewtonSoft的Json序列化foolaa时。. NET,我们得到以下输出…

// foo
{
    "Value": "Hello World!",
    "ValueType": "System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
}
// laa
{
    "Value": 44,
    "ValueType": "System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
}

问题是对Json进行反序列化。. NET不知道它引用的是一个泛型,所以它爆炸了。因此,我需要为这个类编写一个自定义转换器。但是,我不确定如何实例化一个新的泛型实例,其中ValueHolder中用于'T'的数据类型以ValueType的字符串形式存储。

更多信息

我实际上试图序列化/反序列化Dictionary<string,ValueHolder<>>的子类,其中ValueHolder的T对于每个实例都可以不同(当然你不能这样做,我实际上是子类化Dictionary<string,object>然后将解析的ValueHolder放入"对象"),所以我认为正确的方法是将转换器放在字典上,而不是ValueHolder本身。

要从程序集名称创建新对象,可以使用:

Activator.CreateInstance()方法。请参阅此处的文档:

https://msdn.microsoft.com/en-us/library/system.activator.createinstance%28v=vs.110%29.aspx

将class拆分为:

public class ValueTypeBase
{
    public Type ValueType { get; set; }
}
public class ValueHolder<T> : ValueTypeBase
{
    public T Value { get; set; }
}

检查以下代码:

var json = "{"Value": "Hello World!","ValueType": "System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"}";
var valueTypeBase = JsonConvert.DeserializeObject<ValueTypeBase>(json);
var newType = typeof(ValueHolder<>).MakeGenericType(valueTypeBase.ValueType);
var obj = JsonConvert.DeserializeObject(json, newType);

希望对您有所帮助。

将ValueHolder类修改为:

public class ValueHolder<T>
{
    public ValueHolder() { }
    public ValueHolder(T v)
    {
        Value = v;
    }
    public T Value { get; set; }
    public Type ValueType() { return typeof(T); }
}

然后使用下面的代码:

        Type d1 = typeof(ValueHolder<>);
        //Your type -> "System.String"
        Type typeArgs = System.Type.GetType("System.String", false, true);
        Type constructed = d1.MakeGenericType(typeArgs);
        //Your Value-> "Test Value"
        var o = Activator.CreateInstance(constructed, "Test Value");    

使用System.Type.GetType和Type重新构造值。MakeGenericType不是问题(向Ali Amanzadegan和Maarten致敬):

var foo = new ValueHolder<string>() { Value = "Hello World!" };
var laa = new ValueHolder<int>() { Value = 44 };
var daa = new ValueHolder<double> { Value = 123.999 };
//
var jsonFoo = JsonConvert.SerializeObject(foo);
var jsonLaa = JsonConvert.SerializeObject(laa);
var jsonDaa = JsonConvert.SerializeObject(daa);
//
Console.WriteLine(String.Format("{0}{3}{1}{3}{2}", jsonFoo, jsonLaa, jsonDaa, Environment.NewLine));
//
var o = JsonConvert.DeserializeObject<JObject>(jsonFoo);
var typeDescription = o.Properties().FirstOrDefault(p => p.Name == "ValueType");
var type = System.Type.GetType(typeDescription.Value.ToString());
var reFoo = (dynamic)JsonConvert.DeserializeObject(jsonFoo, typeof(ValueHolder<>).MakeGenericType(type));
Console.WriteLine(reFoo.Value);
输出:

Hello World!

对我来说,困难是找到一种方法来提取函数/方法中的功能。我想到的一个可能的解决方案是再次使用动态:

private dynamic reconstructValueHolderFromJson(string json)
{
    var o = JsonConvert.DeserializeObject<JObject>(json);
    var typeDescription = o.Properties().FirstOrDefault(p => p.Name == "ValueType");
    var type = System.Type.GetType(typeDescription.Value.ToString());
    return JsonConvert.DeserializeObject(json, typeof(ValueHolder<>).MakeGenericType(type));
}

现在重建对象看起来像这样(打印值):

var reFoo = reconstructValueHolderFromJson(jsonFoo);
Console.WriteLine("{0}", reFoo.Value);
var reLaa = reconstructValueHolderFromJson(jsonLaa);
Console.WriteLine("{0}", reLaa.Value);
var reDaa = reconstructValueHolderFromJson(jsonDaa);
Console.WriteLine("{0}", reDaa.Value);

输出:

Hello World!
44
123,999

相关内容

  • 没有找到相关文章

最新更新