简体   繁体   English

我怎么知道一个类型是否可以使用Json.NET进行转换?

[英]How can I know if a type is convertible using Json.NET?

I am trying to write an interface for a collection that internally stores data as a JObject 我正在尝试为集合编写一个接口,该集合在内部将数据存储为JObject

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) { ... }
}

In the Add<T> method I want to provide a useful exception if a custom type does not have the DataContract annotation. Add<T>方法中,如果自定义类型没有DataContract批注,我想提供一个有用的异常。 For example, if someone calls: 例如,如果有人打电话:

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

it will throw an exception "Cannot serialize type 'CustomType'. DataContract annotations not found." 它将引发异常"Cannot serialize type 'CustomType'. DataContract annotations not found." if CustomType does not have the proper annotation. 如果CustomType没有正确的注释。

So far I have found a way to get every generic argument in the type definition so I can check them: 到目前为止,我已经找到了一种方法来获取类型定义中的每个泛型参数,以便我可以检查它们:

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

and tried implementing the add method like this: 并尝试实现这样的add方法:

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 think this will work for primitive types and custom types but not for non-generic .NET types since they don't all have DataContract annotations. 我认为这适用于原始类型和自定义类型,但不适用于非泛型.NET类型,因为它们都不具有DataContract注释。 Is there a way to know which types can be serialized by JsonConvert ? 有没有办法知道JsonConvert可以序列化哪些类型?

Json.NET supports pretty much all types, even those without any custom attributes. Json.NET支持几乎所有类型,甚至那些没有任何自定义属性的类型。 Among supported attributes are DataContract, JsonObject, Serializable. 支持的属性包括DataContract,JsonObject,Serializable。 There're numerous ways to make Json.NET include a member in serialization and numerous to make it skip. 有许多方法可以让Json.NET包含序列化中的成员,并且有许多方法可以让它跳过。 If you can't serialize some class, it's more likely caused by issues other than lack of Data* attributes: members throwing exceptions, missing constructors, faulty converters, visibility issues etc. Your error messages are unlikely to be more helpful than those provided by Json.NET. 如果您无法序列化某些类,则更可能是由于缺少Data *属性以外的问题引起的:成员抛出异常,缺少构造函数,错误的转换器,可见性问题等。您的错误消息不太可能比由Json.NET。

You'll have to replicate crazy amounts of logic from Json.NET if you want to test beforehand. 如果你想事先测试,你必须从Json.NET复制疯狂的逻辑。 Checking type and member attributes won't be enough. 检查类型和成员属性是不够的。 Just verifying a converter used for a property would require checking five places at least. 只需验证用于属性的转换器,至少需要检查五个位置。 And even if you do all this work, it will be not enough, because in a new version, a new type or converter or feature or attribute will be introduced in Json.NET and you'll have to do all this again. 即使您完成所有这些工作,也是不够的,因为在新版本中,Json.NET中将引入新类型或转换器或功能或属性,您将不得不再次执行此操作。

The only reliable way to test wether a type can be serialized is to try to serialize it. 测试类型的唯一可靠方法是序列化是尝试序列化它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM