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

ren*_*ene 6 c# wcf .net-4.0

在WCF服务返回一个DataContract与具有无效值(int类型的枚举类型不存在)在客户端抛出的异常的枚举成员的情况是The underlying connection was closed: The connection was closed unexpectedly.
非常奇怪的是此异常被触发,因为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; 
            } 
        }

    }
Run Code Online (Sandbox Code Playgroud)

服务实施

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

客户

var cl = new DtoServiceClient.DtoServiceClient();
var tada = cl.GetData(1);  // connection closed exception
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

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

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

Debug.Assert(Enum.IsDefined(typeof(Rating), value),"value is not valid for this enum");
Run Code Online (Sandbox Code Playgroud)

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

System.Diagnostics.Contracts.Contract.Assert(Enum.IsDefined(typeof(Rating), value));
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Eli*_*bel 3

你可以做一些事情。

在 WCF 端,使用IncludeExceptionDetailInFaults(使用ServiceBehavior属性或在app.config中)。这将使 WCF 向客户端发送详细的异常。请注意,这被认为是“不安全”设置,因为它向客户端公开了服务器堆栈跟踪,因此您应该仅在开发期间使用它。对于生产,您应该使用 WCF 错误处理程序来记录所有服务错误(或打开 WCF 跟踪)。

如果您想使用代码契约在编译时捕获此错误,您可以使用对象不变量:

public class MyDto
{
    public Rating Rating { get; set; }

    [ContractInvariantMethod]
    void Invariant()
    {
        Contract.Invariant(Enum.IsDefined(typeof(Rating), Rating));
    }
}
Run Code Online (Sandbox Code Playgroud)

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

new MyDto {  Rating = (Rating) 42 };
Run Code Online (Sandbox Code Playgroud)