C#反序列化派生并具有引用的对象
我有一个Node类型的对象。 当我按如下方式进行调用时,序列化工作:C#反序列化派生并具有引用的对象,c#,json,serialization,json.net,C#,Json,Serialization,Json.net,我有一个Node类型的对象。 当我按如下方式进行调用时,序列化工作: var nodeSer = JsonConvert.SerializeObject(mynode, Formatting.Indented, new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects }); 我的问题是下面的调用不起作用 var n = JsonConvert.Deseria
var nodeSer = JsonConvert.SerializeObject(mynode, Formatting.Indented,
new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
我的问题是下面的调用不起作用
var n = JsonConvert.DeserializeObject<Node>(nodeSer,
new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects, TypeNameHandling = TypeNameHandling.Auto });
如何设计反序列化调用?Json.NET不会序列化事件,因此存储库基本类型中的
公共事件属性changedeventhandler属性changed
在(反)序列化过程中不会导致问题
但是,该存储库中至少有一种类型具有System.Action
委托,而不是在值更改时要处理的事件,特别是:
不清楚为什么要使用委托而不是事件来实现此目的,但是Json.NET无法反序列化System.Action
。实际上,序列化和反序列化这些委托毫无意义,因为它们在构造函数中被分配用于:
一个简单的解决方案是用
第二个简单的解决方案是用适当的事件替换委托,Json.NET现在将忽略该事件:
public event EventHandler ValueChanged;
如果出于任何原因无法更改这些类型,则可以创建自动忽略所有委托类型属性的:
public class IgnorePropertiesOfTypeContractResolver<T> : IgnorePropertiesOfTypeContractResolver
{
// As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons.
// http://www.newtonsoft.com/json/help/html/ContractResolver.htm
// http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm
// "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance."
static IgnorePropertiesOfTypeContractResolver<T> instance;
static IgnorePropertiesOfTypeContractResolver() { instance = new IgnorePropertiesOfTypeContractResolver<T>(); }
public static IgnorePropertiesOfTypeContractResolver<T> Instance { get { return instance; } }
public IgnorePropertiesOfTypeContractResolver() : base(new[] { typeof(T) }) { }
}
/// <summary>
/// Contract resolver to ignore properties of any number of given types.
/// </summary>
public class IgnorePropertiesOfTypeContractResolver : DefaultContractResolver
{
readonly HashSet<Type> toIgnore;
public IgnorePropertiesOfTypeContractResolver(IEnumerable<Type> toIgnore)
{
if (toIgnore == null)
throw new ArgumentNullException();
this.toIgnore = new HashSet<Type>(toIgnore);
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (property.PropertyType.BaseTypesAndSelf().Any(t => toIgnore.Contains(t)))
{
property.Ignored = true;
}
return property;
}
}
public static class TypeExtensions
{
public static IEnumerable<Type> BaseTypesAndSelf(this Type type)
{
while (type != null)
{
yield return type;
type = type.BaseType;
}
}
}
公共类IgnorePropertiesOfTypeContractResolver:IgnorePropertiesOfTypeControlResolver
{
//从7.0.1开始,出于性能原因,Json.NET建议为“无状态”契约解析器使用静态实例。
// http://www.newtonsoft.com/json/help/html/ContractResolver.htm
// http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm
//“在应用程序中使用协定解析程序的无参数构造函数和缓存实例以获得最佳性能。”
静态IgnorePropertiesOfTypeContractResolver实例;
静态IgnorePropertiesOfTypeContractResolver(){instance=new IgnorePropertiesOfTypeControlResolver();}
公共静态IgnorePropertiesOfTypeContractResolver实例{get{return Instance;}}
public IgnorePropertiesOfTypeContractResolver():base(新[]{typeof(T)}){
}
///
///协定解析程序忽略任意数量的给定类型的属性。
///
公共类IgnorePropertiesOfTypeContractResolver:DefaultContractResolver
{
只读HashSet-toIgnore;
公共IgnorePropertiesOfTypeContractResolver(IEnumerable-toIgnore)
{
if(toIgnore==null)
抛出新ArgumentNullException();
this.toIgnore=新哈希集(toIgnore);
}
受保护的重写JsonProperty CreateProperty(MemberInfo成员、MemberSerialization MemberSerialization)
{
var property=base.CreateProperty(成员,成员序列化);
if(property.PropertyType.BaseTypesAndSelf().Any(t=>toIgnore.Contains(t)))
{
property.Ignored=true;
}
归还财产;
}
}
公共静态类类型扩展
{
公共静态IEnumerable BaseTypes和Self(此类型)
{
while(type!=null)
{
收益型;
type=type.BaseType;
}
}
}
现在使用以下设置序列化:
var settings = new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
ContractResolver = IgnorePropertiesOfTypeContractResolver<System.Delegate>.Instance,
};
var设置=新的JsonSerializerSettings
{
PreserveReferencesHandling=PreserveReferencesHandling.Objects,
ContractResolver=IgnorePropertiesOfTypeContractResolver.Instance,
};
ValueChanged
属性将不再被序列化或反序列化。如果没有一个字符串,我不能确定,但也许你想要?@dbc谢谢,但它没有解决我的问题。但我扩展了描述。你还有别的想法吗?那样的话,你能不能把你的问题包括在一个完整的句子里?看见你本质上是在要求我们花时间重新创建你的问题,以便重现它,这样我们就可以帮助你解决它。尽管如此,看起来您正在尝试序列化类型为Action
的委托,该委托通常未实现(并且没有真正意义)。@dbc感谢您的提示。节点派生自从PropertyChangedBase派生的类。这就是问题所在,对吗?以后,无论何时询问有关异常的stackoverflow问题,请包括异常的完整ToString()
输出,包括消息、回溯和内部异常(如果有)。当询问JSON反序列化时,请包含一个您试图反序列化的JSON示例,该示例再现了问题。
[JsonIgnore]
public Action ValueChanged;
public event EventHandler ValueChanged;
public class IgnorePropertiesOfTypeContractResolver<T> : IgnorePropertiesOfTypeContractResolver
{
// As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons.
// http://www.newtonsoft.com/json/help/html/ContractResolver.htm
// http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm
// "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance."
static IgnorePropertiesOfTypeContractResolver<T> instance;
static IgnorePropertiesOfTypeContractResolver() { instance = new IgnorePropertiesOfTypeContractResolver<T>(); }
public static IgnorePropertiesOfTypeContractResolver<T> Instance { get { return instance; } }
public IgnorePropertiesOfTypeContractResolver() : base(new[] { typeof(T) }) { }
}
/// <summary>
/// Contract resolver to ignore properties of any number of given types.
/// </summary>
public class IgnorePropertiesOfTypeContractResolver : DefaultContractResolver
{
readonly HashSet<Type> toIgnore;
public IgnorePropertiesOfTypeContractResolver(IEnumerable<Type> toIgnore)
{
if (toIgnore == null)
throw new ArgumentNullException();
this.toIgnore = new HashSet<Type>(toIgnore);
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (property.PropertyType.BaseTypesAndSelf().Any(t => toIgnore.Contains(t)))
{
property.Ignored = true;
}
return property;
}
}
public static class TypeExtensions
{
public static IEnumerable<Type> BaseTypesAndSelf(this Type type)
{
while (type != null)
{
yield return type;
type = type.BaseType;
}
}
}
var settings = new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
ContractResolver = IgnorePropertiesOfTypeContractResolver<System.Delegate>.Instance,
};