我正在尝试让 WCF 支持未命名枚举。我创建了一个代理,当它是枚举时它工作得很好。但是,当它是可为 null 的枚举时,它会在反序列化时失败。这是我的代理,是从 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 可为空且有值时,WCF 不会将 int 反序列化为 Enum。
编辑:
我认为这可能与 WCF 如何处理来自代理的反序列化有关。以下是我注意到的一些可能有用的行为。
调用
GetDeserializedObject
时,object obj
将使用已反序列化的对象填充。例如,看起来 WCF 反序列化在代理执行之前就开始了当使用底层类型调用时,
GetDeserializedObject
实际上从未被命中,我认为这是因为代理反序列化仅适用于对象WCF 无法将枚举序列化为值,但它可以很好地处理值的反序列化。
资源:
这是MSDN对于数据合约代理
如何获取可空(和不可空)枚举以严格从值进行序列化和反序列化?
最佳答案
下面这行不让你处理Nullable<Enum>
类型:
if ((false == targetType.IsEnum) || (null == obj))
{
return obj;
}
您还需要检查Nullable<>
明确键入。如下所示:
if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
targetType = targetType.GetGenericArguments()[0];
}
Fiddle这证明了这一点。
关于c# - WCF 枚举按值代理支持动态枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59619094/