2014-10-29 34 views
3

我試圖找出我怎麼能有一個核心對象從我的APIJson.NET在序列化中獲取泛型屬性類型的名稱?

public class Response<T> { 
    public T Data {get;set;} 
} 

其中T是一些對象,具有例如屬性返回

public class Thang { 
    public string Thing {get;set;} 
} 

使用JsonConvert.Serialize(myResponse);將返回T Data財產Data,這是正確的。

但是如果我想使用名稱爲T的類型?因此,Json的反應實際上包括一個名爲Thang而不是Data的屬性,如下所示。

{ 
    "thang": { 
     "thing" : "hey" 
    } 
} 

我很好奇,如果有一個比較簡單的方法,用Json.net做到這一點還是你必須創建一個自定義JsonConverter和使用反射寫作時,爲了獲得T類型的名字嗎?

謝謝。

回答

1

有沒有內置的方式來做到這一點,我知道。

你需要使用一個小的反射,你可能可以使用自定義JsonConverter,但你也可以使用自定義ContractResolver做到在短短的幾行代碼:

public class GenericPropertyContractResolver : 
     CamelCasePropertyNamesContractResolver 
{ 
    private readonly Type genericTypeDefinition; 

    public GenericPropertyContractResolver(Type genericTypeDefinition) 
    { 
     this.genericTypeDefinition = genericTypeDefinition; 
    } 

    protected override JsonProperty CreateProperty(
     MemberInfo member, MemberSerialization memberSerialization) 
    { 
     JsonProperty baseProperty = 
      base.CreateProperty(member, memberSerialization); 

     Type declaringType = member.DeclaringType; 

     if (!declaringType.IsGenericType || 
      declaringType.GetGenericTypeDefinition() != this.genericTypeDefinition) 
     { 
      return baseProperty; 
     } 

     Type declaringGenericType = declaringType.GetGenericArguments()[0]; 

     if (IsGenericMember(member)) 
     { 
      baseProperty.PropertyName = 
       this.ResolvePropertyName(declaringGenericType.Name); 
     } 

     return baseProperty; 
    } 

    // Is there a better way to do this? Determines if the member passed in 
    // is a generic member in the open generic type. 
    public bool IsGenericMember(MemberInfo member) 
    { 
     MemberInfo genericMember = 
      this.genericTypeDefinition.GetMember(member.Name)[0]; 

     if (genericMember != null) 
     { 
      if (genericMember.MemberType == MemberTypes.Field) 
      { 
       return ((FieldInfo)genericMember).FieldType.IsGenericParameter; 
      } 
      else if (genericMember.MemberType == MemberTypes.Property) 
      { 
       PropertyInfo property = (PropertyInfo)genericMember; 

       return property 
        .GetMethod 
        .ReturnParameter 
        .ParameterType 
        .IsGenericParameter; 
      } 
     } 

     return false; 
    } 
} 

,那麼你可以使用這樣的:

var settings = new JsonSerializerSettings(); 
settings.ContractResolver = new GenericPropertyContractResolver(typeof(Response<>)); 

string serialized = JsonConvert.SerializeObject(new Response<Thang> 
{ 
    Data = new Thang { Thing = "Hey" } 
}, settings); 

可能是一個更簡單的事情是把你的類變成Dictionary序列化之前。

我也有點麻煩,如果一個封閉的泛型類型的屬性對應於一個泛型屬性的開放泛型類型 - 任何提示,將不勝感激。

例如:https://dotnetfiddle.net/DejOL2

相關問題