【发布时间】:2020-01-06 21:16:16
【问题描述】:
我正在尝试让 WCF 支持未命名的枚举。我创建了一个代理项,它在枚举时可以正常工作。但是,当它是一个可为空的枚举时,它在反序列化时会失败。这是我的代理,它是从 article 修改的,我的代码不同,因为我不想提供已知类型:
public class EnumValueDataContractSurrogate : IDataContractSurrogate
{
#region Interface Implementation
public Type GetDataContractType(Type type)
{
return type;
}
public object GetObjectToSerialize(object obj, Type targetType)
{
if (null == obj)
{
return obj;
}
if (targetType.IsEnum)
{
return EnumExtensions.ChangeToUnderlyingType(targetType, obj);
}
if (targetType.IsNullable() && targetType.GetUnderlyingType().IsEnum)
{
return (int?)obj;
}
return obj;
}
// This Method is never invoked for targetType enum/enum?
// However all the other parameters work fine
public object GetDeserializedObject(object obj, Type targetType)
{
if (targetType.IsNullable())
{
targetType = targetType.GetUnderlyingType();
}
if ((false == targetType.IsEnum) || (null == obj))
{
return obj;
}
var stringObj = obj as string;
if (null != stringObj)
{
return Enum.Parse(targetType, stringObj);
}
return Enum.ToObject(targetType, obj);
}
public void GetKnownCustomDataTypes(Collection<Type> customDataTypes)
{
//not used
return;
}
public object GetCustomDataToExport(Type clrType, Type dataContractType)
{
//Not used
return null;
}
public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType)
{
//not used
return null;
}
public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
{
//not used
return null;
}
public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit)
{
//not used
return typeDeclaration;
}
#endregion
}
public static object ChangeToUnderlyingType(Type enumType, object value)
{
return Convert.ChangeType(value, Enum.GetUnderlyingType(enumType));
}
当 Enum 不可为空时,一切都可以反序列化。
当 Enum 可以为 null 时,WCF 不会将 int 反序列化为 Enum。
编辑:
我认为这可能与 WCF 如何处理来自代理的反序列化有关。以下是我注意到的一些可能有用的行为。
调用
GetDeserializedObject时,object obj将填充一个已经反序列化的对象。例如,看起来 WCF 反序列化在代理项之前就开始了当使用底层类型调用
GetDeserializedObject时,我认为这是因为代理反序列化仅适用于对象WCF 无法将枚举序列化为值,但它可以很好地处理从值反序列化。
资源:
这是数据合约代理的MSDN
如何获得可空(和不可空)枚举以严格从值序列化和反序列化?
【问题讨论】:
-
嗯,根据文档
GetDeserializedObject方法是在反序列化过程之后调用的。如果失败,则不会调用该方法。他们在反序列化之前拦截它的唯一方法是修改GetDataContractType方法。我不确定,但如果枚举合约传递到此方法中,您可能会拦截它们是如何反序列化的。 -
@Eldar 是的,我一直在尝试反序列化,我认为这是怎么做的,但我无法让它工作。如果您知道任何方法可以始终将枚举序列化为它们的值,我会接受它作为答案