问题描述
我在以下代码中收到以下错误:
I get the following error with the code below:
代码:
public class Response<T> : Response
{
private string PropName
{
get
{
return typeof(T).Name;
}
}
[JsonProperty(PropName)]
public T Data { get; set; }
}
推荐答案
您尝试做的事情是可能的,但并非无关紧要的,仅使用JSON.NET的内置属性无法完成.您将需要一个自定义属性和一个自定义合同解析器.
What you're trying to do is possible, but not trivial, and can't be done with only the built-in attributes from JSON.NET. You'll need a custom attribute, and a custom contract resolver.
这是我想出的解决方案:
Here's the solution I came up with:
声明此自定义属性:
[AttributeUsage(AttributeTargets.Property)]
class JsonPropertyGenericTypeNameAttribute : Attribute
{
public int TypeParameterPosition { get; }
public JsonPropertyGenericTypeNameAttribute(int position)
{
TypeParameterPosition = position;
}
}
将其应用于您的Data
属性
public class Response<T> : Response
{
[JsonPropertyGenericTypeName(0)]
public T Data { get; set; }
}
(0是T
在Response<T>
通用类型参数中的位置)
(0 is the position of T
in Response<T>
's generic type parameters)
声明以下合同解析器,它将查找JsonPropertyGenericTypeName
属性并获取类型参数的实际名称:
Declare the following contract resolver, which will look for the JsonPropertyGenericTypeName
attribute and get the actual name of the type argument:
class GenericTypeNameContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var prop = base.CreateProperty(member, memberSerialization);
var attr = member.GetCustomAttribute<JsonPropertyGenericTypeNameAttribute>();
if (attr != null)
{
var type = member.DeclaringType;
if (!type.IsGenericType)
throw new InvalidOperationException($"{type} is not a generic type");
if (type.IsGenericTypeDefinition)
throw new InvalidOperationException($"{type} is a generic type definition, it must be a constructed generic type");
var typeArgs = type.GetGenericArguments();
if (attr.TypeParameterPosition >= typeArgs.Length)
throw new ArgumentException($"Can't get type argument at position {attr.TypeParameterPosition}; {type} has only {typeArgs.Length} type arguments");
prop.PropertyName = typeArgs[attr.TypeParameterPosition].Name;
}
return prop;
}
}
在您的序列化设置中对此解析器进行序列化:
Serialize with this resolver in your serialization settings:
var settings = new JsonSerializerSettings { ContractResolver = new GenericTypeNameContractResolver() };
string json = JsonConvert.SerializeObject(response, settings);
这将为Response<Foo>
{
"Foo": {
"Id": 0,
"Name": null
}
}
这篇关于如何获得< T>的名称从泛型类型并将其传递到JsonProperty()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!