我们有很多WCF客户和服务。这些服务都共享一个公共数据包,其中包括一个主程序集,其中包含每个数据协定中使用的所有枚举。当此数据包的任何枚举发生更改时,例如添加新成员,从业务角度来看,并非所有服务都需要更新才能利用该更改,因为它与其功能无关。
但是,当此枚举传递了未知值时,它会导致错误,因为它发送的是字符串值,该值无法映射到整数。理想情况下,我们希望编写某种格式化程序或行为来拦截枚举值并确定其是否有效。如果有效,则继续正常通话。如果无效,则仅使用整数值并忽略字符串值。显然,这种方法在出于业务原因需要此枚举的情况下不起作用,但大多数时候这些枚举只需要通过请求传递即可。
这可能可以通过添加包含枚举的 int 和 string 值的自定义标头,然后在反序列化之前处理它来实现,但是我无法让这样的东西正常工作,并且标头似乎没有保留我的信息需要(但这可能是一个单独的问题;我还不能确定)。
以下是之前使用代理尝试的示例,取自this,但错误似乎发生在点击此代码之前,因此无法正常工作。
/// <summary>
/// Custom Data Contract Surrogate that De/Serializes enum values as their underlying values instead of strings (default WCF)
/// To avoid issues with newly introduced enum values on updated WCF services and older clients.
/// </summary>
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.IsNullable())
{
targetType = targetType.GetUnderlyingType();
}
if (targetType.IsEnum)
{
return EnumExtensions.ChangeToUnderlyingType(targetType, obj);
}
return obj;
}
public object GetDeserializedObject(object obj, Type targetType)
{
if ((false == targetType.IsEnum) || (null == obj))
{
return obj;
}
if (targetType.IsNullable())
{
targetType = targetType.GetUnderlyingType();
}
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
}
我想要做的事情是否可能,忽略解决方案的丑陋?我也写了一个 MessageFormatter,但也没有让它工作。
我有一个建议:WCF中有一个方法:BeforeCall。
在发送客户端调用之前,即在将请求传递给服务之前,调用 BeforeCall 方法。
可以帮助您验证客户端发送的枚举数据是否有效。
public object BeforeCall(string operationName, object[] inputs)
{
// Judge
}
我认为这是在发送请求之前判断请求的一种非常有效的方法。