Проверяйте enum null, если он не обнуляем и не имеет нулевых опций - PullRequest
0 голосов
/ 20 июня 2019

Это отличается от вопросов, подобных приведенным ниже

Как определить, установлено ли свойство enum?C #

Я работаю над созданием службы WCF Rest с использованием существующих классов DataContract. Я не могу изменить типы данных свойств, такие как enum, на enum?а также не может добавить новую опцию в мое перечисление, например undefined, none или по умолчанию установить что-либо, поскольку, если я сделаю какое-либо из этих изменений, это окажет сильное влияние, и многие приложения будут зависеть от него .

Обычнолюди вызывают мою службу WCF REST с помощью приложений, таких как POSTMAN, куда они отправляют данные json, как показано ниже, где Gender - это перечисление с Male, Female, Transgender и т. д. Если они не отправляют его, моя служба выдает исключение и Я хочудобавить логику проверки, чтобы проверить, является ли enum нулевым или нет, когда QA вызывает мой сервис, используя POSTMAN, и отправляет данные JSON, даже если они не обнуляются и также не имеют никаких значений None, Null в моем enum? Если это NULL Iхочу отправить ArguementNullException обратно вызывающим абонентам с хорошим сообщением.Я хочу изящно справиться с этой ситуацией.

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

Ниже хорошо

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

Ниже выдает ошибку

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

РЕШЕНИЕ:

Спасибо pswg за указание в правильном направлении, и я отметил его ответ ниже.Я использую Newtonsoft, поэтому я сделал, как показано ниже

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

Ответы [ 2 ]

2 голосов
/ 20 июня 2019

Кроме очевидной опции деформации перечисления в классе, которая может не работать в вашей конкретной ситуации, вы можете установить для переменной enum целое число вне диапазона перечисления.После этого вы можете проверить, определено ли целое число в перечислении.Поскольку 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
        }
1 голос
/ 20 июня 2019

Примечание: ответы ниже используют DataContracts, поскольку вы указали в своем вопросе, но аналогичные решения существуют для сериализации Json.Net .

Вы можете использовать [DataMember(EmitDefaultValue = false)], чтобы игнорировать случаи, когда Gender вообще не указан.В этом случае возвращаемое значение будет равно любому члену enum, которому присвоено значение 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 }
}

Для обработки случаев, когда предоставляется пустая строка вместо действительного значения или вообще без значения, вы можете использовать этот маленький хакерский прием:

[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 }
}

Однако это несколько неловко и им легко злоупотреблять.Я бы рекомендовал осторожность с этим подходом.Как уже упоминали другие, мы обычно хотим выдавать ошибки всякий раз, когда недопустимые значения предоставляются функции / API.Под «быстрым провалом» вы даете пользователю, пытающемуся использовать API, знать, что он создал запрос, который в определенный момент может привести к неожиданным результатам.

...