Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何知道类型是否可以使用Json.NET转换?_C#_.net_Json_Json.net_Datacontractjsonserializer - Fatal编程技术网

C# 如何知道类型是否可以使用Json.NET转换?

C# 如何知道类型是否可以使用Json.NET转换?,c#,.net,json,json.net,datacontractjsonserializer,C#,.net,Json,Json.net,Datacontractjsonserializer,我正在尝试为一个集合编写一个接口,该集合在内部将数据存储为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

我正在尝试为一个集合编写一个接口,该集合在内部将数据存储为
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) { ... }
}
如果
CustomType
没有正确的注释,它将抛出异常
“无法序列化类型'CustomType'。找不到DataContract注释。”

到目前为止,我已经找到了一种方法来获取类型定义中的每个泛型参数,以便检查它们:

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;
}
private IEnumerable GetGenericargumentsRecursive(类型)
{
如果(!type.IsGenericType)生成返回类型;
foreach(type.GetGenericArguments()中的var genericArg)
foreach(GetGenericArgumentsRecursive(genericArg)中的变量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))));
}
public void Add(字符串键,T值)
{
foreach(getGenericargumentsRecursive中的变量类型(typeof(T)))
{
如果(!type.IsPrimitive&&!Attribute.IsDefined(type,typeof(DataContractAttribute)))
抛出新异常(“无法序列化类型“{0}”。找不到DataContract批注。”,typeof(T));
}
Add(新的JProperty(key,JToken.Parse(jsonvert.SerializeObject(value)));
}

我认为这适用于基本类型和自定义类型,但不适用于非泛型.NET类型,因为它们并不都有
DataContract
注释。有没有办法知道哪些类型可以被
JsonConvert
序列化?

Json.NET几乎支持所有类型,即使是没有任何自定义属性的类型。支持的属性包括DataContract、JsonObject和Serializable。有很多方法可以让Json.NET在序列化中包含一个成员,也有很多方法可以让它跳过。如果无法序列化某个类,则很可能是由于缺少Data*属性以外的问题造成的:成员抛出异常、缺少构造函数、错误的转换器、可见性问题等。您的错误消息不太可能比Json.NET提供的错误消息更有帮助

如果您想事先进行测试,就必须从Json.NET复制大量的逻辑。检查类型和成员属性是不够的。仅验证用于属性的转换器就需要检查至少五个位置。即使您完成了所有这些工作,这也是不够的,因为在一个新版本中,Json.NET中会引入一个新的类型、转换器、特性或属性,您必须再次完成所有这些工作


测试类型是否可以序列化的唯一可靠方法是尝试序列化它。

Json.Net不需要
DataContract
属性,几乎所有类型都可以通过它序列化。
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))));
}