当enum无法序列化时,提前失败或明显抛出

在WCF服务返回带有枚举成员且具有无效值(Enum类型中不存在的int)的DataContract的情况下,客户端上抛出的exception是The underlying connection was closed: The connection was closed unexpectedly.
奇怪的是,这个exception被触发,因为DataContractSerializer无法在连接的服务器端序列化。

我宁愿在服务器端运行时向我抛出一些更有用的东西并且更重要,但可能是编译器警告……

WCF服务合同

  [ServiceContract] public interface IDtoService { [OperationContract] MyDto GetData(int value); } public enum Rating { None = 0, NotSet = 1, Somevalue = 34 } [DataContract] public class MyDto { Rating _rate; [DataMember] public Rating Rating { get { return _rate; } set { _rate = value; } } } 

服务实施

  public class DtoService : IDtoService { public MyDto GetData(int value) { var dto = new MyDto { Rating = (Rating) 42 }; // not in ENUM! return dto; } } 

客户

 var cl = new DtoServiceClient.DtoServiceClient(); var tada = cl.GetData(1); // connection closed exception 

为了抛出实际的exception,我不得不在调试选项VS2010和“exception”对话框中禁用“仅启用我的代码”,为“公共语言运行时exception”启用“抛出”

有了这些设置,有价值的例外是:

SerializationException
枚举值“42”对于“WcfService1.Rating”类型无效,无法序列化。 确保存在必要的枚举值,并且如果类型具有DataContractAttribute属性,则使用EnumMemberAttribute属性标记

这是因为调试器对AFAIK可以忽略的所有其他类型的抛出exception非常嘈杂。

我可以尝试在没有噪音的情况下抛出此exception吗?

我可以调整或添加WCF管道吗?

在返工成本的早期失败的一种可能解决方案是在枚举成员的setter中添加额外的Assert:

 Debug.Assert(Enum.IsDefined(typeof(Rating), value),"value is not valid for this enum"); 

我尝试的另一种方法是添加合同,希望可以产生警告。 我找不到比基本上Debug.Assert的副本更好的东西。

 System.Diagnostics.Contracts.Contract.Assert(Enum.IsDefined(typeof(Rating), value)); 

是否有选项让编译器为我发出此检查或是否有我不知道的替代方案?
(我也尝试使用check for arithmetic overflow/underflow启用编译而不期望它成功)

CodeContracts会发出警告,(你必须使用Implicit Enum写入义务),尽管这并没有真正帮助

实际值可能不在为此枚举值定义的范围内

此行为是在VS2010 / .Net 4.0上下文中。

你可以做一些事情。

在WCF端,使用IncludeExceptionDetailInFaults (使用ServiceBehavior属性或在app.config中 )。 这将使WCF向客户端发送详细的例外。 请注意,这被视为“不安全”设置,因为它将服务器堆栈跟踪暴露给客户端,因此您应该只在开发期间使用它。 对于生产,您应该使用WCFerror handling程序来记录所有服务错误(或打开WCF跟踪)。

如果要在编译期间使用代码约定来捕获此错误,则可以使用对象不变量:

 public class MyDto { public Rating Rating { get; set; } [ContractInvariantMethod] void Invariant() { Contract.Invariant(Enum.IsDefined(typeof(Rating), Rating)); } } 

如果启用静态分析,您将在此行收到警告:

 new MyDto { Rating = (Rating) 42 };