使用ExpandoObject
时,是否可以忽略Delegate
属性,尤其是JsonConvert(expando, formatting, serializerSettings)
类型的属性?
基本上我试图忽略此示例expando对象中func
属性的所有解析:
//{
// func: () => {}
//}
Action func = () => {};
dynamic expando = new ExpandoObject();
expando.func = func;
// should be empty object {}
string json = JsonConvert(expando, formatting, serializerSettings);
我尝试的第一件事就是重写转换器。不幸的是,这并不起作用,因为我看到CanConvert
递归调用Action
- > DelegateEntry
- >一些通用类型 - > RuntimeMethodInfo
。
private class ExpandoObjectIgnoreConverter : ExpandoObjectConverter
{
public override bool CanConvert(Type objectType)
{
if (typeof(Delegate).IsAssignableFrom(objectType))
{
return false;
}
return base.CanConvert(objectType);
}
}
一种有效的方法是在序列化设置和合同解析器中使用错误处理程序。当我抛出错误时,将忽略属性的所有进一步处理,即Action
- > DelegateEntry
- >一些通用类型 - > RuntimeMethodInfo
击>。但是,如果可能的话,我希望比抛出异常更优雅。
错误处理程序:
serializationSettings.Error = (sender, args) =>
{
if (args.ErrorContext.Error is InvalidCastException)
{
args.ErrorContext.Handled = true;
}
}
合同解析员:
private class ExpandoObjectContractResolver : DefaultContractResolver
{
public override JsonContract ResolveContract(Type type)
{
if (typeof(Delegate).IsAssignableFrom(type))
{
throw new InvalidCastException();
}
else
{
return base.ResolveContract(type);
}
}
}
我使用edge库在C#进程中编写nodejs脚本。我试图从C#中删除返回的javascript对象中的函数,因为它们被分配了一个Delegate
类型,与JsonConvert
不能很好地匹配。
答案 0 :(得分:2)
ExpandoObjectConverter
没有任何自定义代码写 ExpandoObject
。相反,它会覆盖JsonConverter.CanWrite
以返回false
,从而允许将expando序列化为IDictionary<string, object>
。
因此,您可以自行覆盖CanWrite
和WriteJson()
,以便在序列化之前过滤不需要的键/值对:
public class FilteredExpandoObjectConverter : ExpandoObjectConverter
{
public override bool CanWrite { get { return true; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var expando = (IDictionary<string, object>)value;
var dictionary = expando
.Where(p => !(p.Value is System.Delegate))
.ToDictionary(p => p.Key, p => p.Value);
serializer.Serialize(writer, dictionary);
}
}
然后在设置中使用转换器,如下所示:
var formatting = Formatting.Indented;
var serializerSettings = new JsonSerializerSettings
{
Converters = { new FilteredExpandoObjectConverter() },
};
var json = JsonConvert.SerializeObject(expando, formatting, serializerSettings);
请注意,这只会过滤ExpandoObject
直接拥有的代理值。如果您在某个POCO中有一个包含某些委托或委托值成员的集合,则不会使用此代码对其进行过滤。
示例fiddle。