2013-09-09 2 views
4

Я пытаюсь написать интерфейс для коллекции, которая внутренне хранят данные как JObjectКак узнать, может ли тип конвертироваться с помощью Json.NET?

internal class JsonDataSet : IDataSet 
{ 
    private JObject Document { get; set; } 

    // The following methods are from the IDataSet interface 
    public int Count { ... } 
    public void Add<T>(string key, T value) { ... } 
    public T GetItem<T>(string key) { ... } 
    public bool ContainsKey(string key) { ... } 
} 

В Add<T> методе, который я хочу, чтобы обеспечить полезное исключение, если пользовательский тип не имеет DataContract аннотации. Например, если кто-то звонит:

dataSet.Add<IDictionary<string, IList<CustomType>>>(dict); 

он будет бросать исключение "Cannot serialize type 'CustomType'. DataContract annotations not found." если CustomType не имеет надлежащую аннотацию.

До сих пор я нашел способ, чтобы получить каждый общий аргумент в определении типа, так что я могу проверить их:

private IEnumerable<Type> GetGenericArgumentsRecursively(Type type) 
{ 
    if (!type.IsGenericType) yield return type; 

    foreach (var genericArg in type.GetGenericArguments()) 
     foreach (var yieldType in GetGenericArgumentsRecursively(genericArg)) 
      yield return yieldType; 
} 

и попытался реализации способа добавить так:

public void Add<T>(string key, T value) 
{ 
    foreach(var type in GetGenericArgumentsRecursively(typeof(T))) 
    { 
     if(!type.IsPrimitive && !Attribute.IsDefined(type, typeof(DataContractAttribute))) 
      throw new Exception("Cannot serialize type '{0}'. DataContract annotations not found.", typeof(T)); 
    } 

    Document.Add(new JProperty(key, JToken.Parse(JsonConvert.SerializeObject(value)))); 
} 

I подумайте, что это будет работать для примитивных типов и настраиваемых типов, но не для не общих типов .NET, так как у них не все есть аннотации DataContract. Есть ли способ узнать, какие типы могут быть сериализованы на JsonConvert?

+2

Вам не нужен атрибут DataContract для Json.Net, и почти все его типы могут быть сериализованы. – EZI

ответ

6

Json.NET поддерживает практически все типы, даже те, у которых нет каких-либо пользовательских атрибутов. Среди поддерживаемых атрибутов - DataContract, JsonObject, Serializable. Существует множество способов заставить Json.NET включать член в сериализацию и множество, чтобы пропустить его. Если вы не можете сериализовать какой-либо класс, это скорее связано с проблемами, отличными от отсутствия атрибутов Data *: члены, бросающие исключения, отсутствующие конструкторы, неисправные преобразователи, проблемы с видимостью и т. Д. Ваши сообщения об ошибках вряд ли будут более полезными, чем те, которые предоставляются Json.NET.

Вам нужно будет воспроизвести сумасшедшие суммы логики от Json.NET, если вы хотите протестировать заранее. Недостаточно проверить тип и атрибуты элемента. Просто проверка конвертера, используемого для свойства, потребует проверки по крайней мере пяти мест. И даже если вы выполните всю эту работу, этого будет недостаточно, потому что в новой версии в Json.NET будет введен новый тип или конвертер или функция или атрибут, и вам придется все это повторить.

Единственный надежный способ тестирования типа типа может быть сериализован, чтобы попытаться его сериализовать.

Смежные вопросы