简体   繁体   English

当枚举不可为空并且没有任何空选项时,请检查其为空

[英]Check enum null when it is not nullable and do not have any null options

This is different from questions like below 这与下面的问题不同

How to tell if an enum property has been set? 如何判断是否已设置枚举属性? C# C#

I am working on creating WCF Rest service using existing DataContract classes. 我正在使用现有的DataContract类创建WCF Rest服务。 I cannot change property datatypes like enum to enum? 我不能将枚举之类的属性数据类型更改为枚举吗? and also cannot add new option in my enum like undefined, none, or by default set anything since if I do anyone of these changes it will be firm wide impact and many applications depend on it. 而且也无法在枚举中添加未定义,无选择或默认设置的任何新选项,因为如果我进行这些更改中的任何一个,都会对整个公司产生广泛的影响,并且许多应用程序都依赖它。

Normally people call my WCF REST Service using applications like POSTMAN where they send in json data like below in which Gender is an enum with Male, Female, Transgender, etc. If they do not send it my service throws exception and I want to add validation logic to check whether enum is null or not when QA scall my service using POSTMAN and send JSON data even though it is not nullable and also do not have any None, Null options in my enum? 通常,人们使用POSTMAN之类的应用程序来调用我的WCF REST服务,他们在其中发送json数据(如下所示),其中Gender是一个包含Male,Female,Transgender等的枚举。如果不发送,我的服务将引发异常,我想添加验证QA使用POSTMAN调用我的服务并发送JSON数据(即使该属性不可为空并且在我的枚举中也没有任何None,Null选项)时,检查枚举是否为null的逻辑? If it is NULL I want to send ArgumentNullException back to callers with nice message. 如果它为NULL,我想将ArgumentNullException发送回带有好消息的调用方。 I want to handle this situation gracefully. 我想优雅地处理这种情况。

public enum Gender 
{
    Male = 0,
    Female = 1,
    Transgender = 2
}

Below is good 下面不错

{
      "Name" : "XXX"
      "Gender" : "1"
}

Below throws error 下面抛出错误

{
      "Name" : "XXX"
      "Gender" : ""
}

SOLUTION: 解:

Thanks to pswg for pointing in correct direction and I marked his answer below. 感谢pswg指出正确的方向,我在下面标记了他的答案。 I am using Newtonsoft so I did like below 我正在使用Newtonsoft,所以我在下面做了

string stringfydata = Newtonsoft.Json.JsonConvert.SerializeObject(requestGender);
if(string.IsNullOrEmpty(stringfydata))
{
   throw new ArgumentNullException("Gender value cannot be NULL or Empty.");
}

Other than the obvious option of warping the enum in a class, which might not work in your specific situation, you can set the enum variable to a integer out of the enum range. 除了显而易见的使类中的枚举变形的选项(在您的特定情况下可能不起作用)之外,您可以将enum变量设置为超出枚举范围的整数。 After that, you can then check to see if the integer is defined within the enum. 之后,您可以检查是否在枚举中定义了整数。 Since C# does not check enumerations , you can do the following: 由于C# 不检查枚举 ,因此您可以执行以下操作:

    public enum Gender
    {
        Male = 0,
        Female = 1,
        Transgender = 2
    }

    public int HandleGender(string strJsonGender){
        if (strJsonGender == "")
        {
            return -1;
        }
        else {
            // Get int representation of the gender
            return (int)((Gender)Enum
                    .Parse(typeof(Gender),
                           strJsonGender, true));
        }
    }

    public void MainMethod(string strJsonGender) {
        Gender gVal;
        int iVal = HandleGender(strJsonGender);

        if (Enum.IsDefined(typeof(Gender), iVal))
        {
            // Handle if the an actual gender was specified
            gVal = (Gender)iVal;
        }
        else { 
            // Handle "null" logic
        }

Note: the answers below use DataContracts since you've indicated in your question, but similar solutions exist for Json.Net serialization . 注意:由于您已经在问题中指出,因此下面的答案使用DataContracts ,但是Json.Net序列化也存在类似的解决方案。

You can use [DataMember(EmitDefaultValue = false)] to ignore cases where Gender is not specified at all. 您可以使用[DataMember(EmitDefaultValue = false)]忽略根本未指定Gender情况。 In this case, the value that's returned will be whatever enum member is assigned a value of 0 (note that if no member has that value, you'll still get a value of 0 , which could be useful for you). 在这种情况下,返回的值将是为枚举成员分配的值均为0的值(请注意,如果没有成员具有该值,则仍将获得值0 ,这可能对您有用)。

[DataContract]
class Person
{
    [DataMember]
    public string Name { get; set; }

    [DataMember(EmitDefaultValue = false)]
    public Gender Gender { get; set; }
}


void Main()
{
    var json = "{\"Name\": \"XXX\"}";
    var ser = new DataContractJsonSerializer(typeof(Person));
    var obj = ser.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json)));
    obj.Dump(); // Person { Name = "XXX", Gender = Male }
}

To handle cases where an empty string is provided instead of a valid value or no value at all, you can use this hacky little trick: 要处理提供空字符串而不是有效值或根本没有值的情况,可以使用以下技巧:

[DataContract]
class Person
{
    [DataMember]
    public string Name { get; set; }

    [IgnoreDataMember]
    public Gender Gender
    {
        get
        {
            if (GenderValue.GetType() == typeof(string))
            {
                Enum.TryParse((string)GenderValue, out Gender result);
                return result;
            }
            return (Gender)Convert.ToInt32(GenderValue);
        }
        set
        {
            GenderValue = value;
        }
    }

    [DataMember(Name = "Gender", EmitDefaultValue = false)]
    private object GenderValue { get; set; }
}


void Main()
{
    var json = "{\"Name\": \"XXX\", \"Gender\": \"\"}";
    var ser = new DataContractJsonSerializer(typeof(Person));
    var obj = ser.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json)));
    obj.Dump(); // Person { Name = "XXX", Gender = Male }
}

However, this is somewhat awkward and can be easily abused. 但是,这有点尴尬,很容易被滥用。 I'd recommend caution with this approach. 我建议您谨慎使用此方法。 As others have mentioned, we typically want to throw errors whenever invalid values are provided to a function / API. 正如其他人提到的,我们通常希望在将无效值提供给函数/ API时引发错误。 By 'failing fast' you let the user attempting to use the API know that they've constructed a request that's likely to produce unexpected results at some point. 通过“快速失败”,您可以使尝试使用API​​的用户知道他们已经构建了一个可能在某个时候产生意外结果的请求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM