如何获得<T>的名字从泛型类型并将其传递给 JsonProperty()?

时间:2023-04-25
本文介绍了如何获得<T>的名字从泛型类型并将其传递给 JsonProperty()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

下面的代码出现以下错误:

I get the following error with the code below:

"非静态字段、方法或属性 'Response.PropName'"

"An object reference is required for the non-static field, method, or property 'Response.PropName'"

代码:

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 属性

Apply it to your Data property

public class Response<T> : Response
{
    [JsonPropertyGenericTypeName(0)]
    public T Data { get; set; }
}

(0是TResponse的泛型类型参数中的位置)

(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
  }
}

这篇关于如何获得&lt;T&gt;的名字从泛型类型并将其传递给 JsonProperty()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:为动态对象的属性返回 null 的空合并运算符 下一篇:如何使 Json.Net 跳过空集合的序列化

相关文章