Использование generi c способа разбора Enums - PullRequest
0 голосов
/ 03 мая 2020

Мне нужно было решение для парсинга string в int для использования с InputSelect Blazor.

Я нашел это решение , которое работает довольно хорошо .

Теперь с моими моделями

public class Book
    {
        [Required]
        public int Id { get; set; }
        [Required]
        public int CategoryId { get; set; }
        public Category Category { get; set; }
        ...
        [Required]
        public EnumLanguages Language { get; set; }
}

public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Я могу использовать его на своей странице Razor следующим образом:

<InputSelectNumber id="category" @bind-Value="@Book.CategoryId">
       @foreach (var category in Categories)
       {
            <option value="@category.Id">@category.Name</option>
       }
</InputSelectCustom>

С этим я могу использовать свой CategoryId (что является int) непосредственно на моем теге InputSelectNumber. Все идет нормально.

Теперь мне нужно сделать то же самое для перечислений, таких как EnumLanguages ​​

public enum EnumLanguages
{
    English,
    French
}

Я обновил класс InputSelectNumber следующим образом:

public class InputSelectNumber<T> : InputSelect<T>
{
    protected override bool TryParseValueFromString(string value, out T result, out string validationErrorMessage) 
    {
        if (typeof(T) == typeof(int))
        {
            if (int.TryParse(value, out var resultInt))
            {
                result = (T)(object)resultInt;
                validationErrorMessage = null;
                return true;
            }
            else
            {
                result = default;
                validationErrorMessage = "The chosen value is not valid.";
                return false;
            }
        }
        else 
        if (typeof(T) == typeof(EnumLanguages))
        {
            if (Enum.TryParse<EnumLanguages>(value, out var resultEnum))
            {
                result = (T)(object)resultEnum;
                validationErrorMessage = null;
                return true;
            }
            else
            {
                result = default;
                validationErrorMessage = "The chosen value is not valid.";
                return false;
            }
        }
        else
        {
            return base.TryParseValueFromString(value, out result, out validationErrorMessage);
        }
    }
}

И использую его:

<InputSelectNumber @bind-Value="Book.Language">
      <option value="English">English</option>
      <option value="French">French</option>
</InputSelectCustom>

Как видите, я добавил второй блок кода, где я жестко закодировал EnumLanguages в своем коде. Но я бы предпочел использовать обобщенный код c для Enums, но я не знаю, возможно ли это. Обратите внимание, что я не могу изменить сигнатуру метода, потому что это переопределение.

1 Ответ

1 голос
/ 05 мая 2020

Вы можете использовать такой способ:

 protected override bool TryParseValueFromString(string value, out T result, out string validationErrorMessage)
    {
        if (typeof(T) == typeof(int))
        {
            if (int.TryParse(value, out var resultInt))
            {
                result = (T)(object)resultInt;
                validationErrorMessage = null;
                return true;
            }
            else
            {
                result = default;
                validationErrorMessage = "The chosen value is not valid.";
                return false;
            }
        }
        else  if (typeof(T).IsEnum)
        {
            if (EnumTryParse<T>(value, out var resultEnum))
            {
                result = (T)(object)resultEnum;
                validationErrorMessage = null;
                return true;
            }
            else
            {
                result = default;
                validationErrorMessage = "The chosen value is not valid.";
                return false;
            }
        }
        else
        {
            return base.TryParseValueFromString(value, out result, out validationErrorMessage);
        }
    }

И этот метод степени:

public static bool EnumTryParse<T>(string input, out T theEnum)
    {
        foreach (string en in Enum.GetNames(typeof(T)))
        {
            if (en.Equals(input, StringComparison.CurrentCultureIgnoreCase))
            {
                theEnum = (T)Enum.Parse(typeof(T), input, true);
                return true;
            }
        }

        theEnum = default(T);
        return false;
    }

Окончательное использование

    <InputSelectNumber @bind-Value="@language" T="@EnumLanguages">
    <option value="English">English</option>
    <option value="French">French</option>
</InputSelectNumber>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...