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

How to get the name of lt;Tgt; from generic type and pass it into JsonProperty()?(如何获得lt;Tgt;的名字从泛型类型并将其传递给 JsonProperty()?)
本文介绍了如何获得<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()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

Force JsonConvert.SerializeXmlNode to serialize node value as an Integer or a Boolean(强制 JsonConvert.SerializeXmlNode 将节点值序列化为整数或布尔值)
Using JSON to Serialize/Deserialize TimeSpan(使用 JSON 序列化/反序列化 TimeSpan)
Could not determine JSON object type for type quot;Classquot;(无法确定类型“Class的 JSON 对象类型.)
How to deserialize a JSONP response (preferably with JsonTextReader and not a string)?(如何反序列化 JSONP 响应(最好使用 JsonTextReader 而不是字符串)?)
how to de-serialize JSON data in which Timestamp it-self contains fields?(如何反序列化时间戳本身包含字段的JSON数据?)
JSON.Net custom contract serialization and Collections(JSON.Net 自定义合约序列化和集合)