Как привести строку к свойству класса - PullRequest
0 голосов
/ 13 марта 2020

У меня есть модель для моей базы данных (использующая efcore для перевода между моделью и базой данных), которая содержит строку, которая может принимать три значения.

Чтобы лучше контролировать значения строк, поступающие в БД, я создал перечисление сортов (что невозможно сделать в C#, поэтому я следовал этой модели ).

public class MyModelClass 
{
    public int Id { get; protected set; }
    public string MyString { get; protected set; }

    public MyModelClass(int id, MyTranslatingType type)
    {
        Id = id;
        MyString = type.Value;
    }

    public class MyTranslatingType
    {
        private MyTranslatingType(string value) { Value = value; }

        public string Value { get; set; }

        public static MyTranslatingType FirstType
            => new MyTranslatingType(nameof(FirstType));

        public static MyTranslatingType SecondType
            => new MyTranslatingType (nameof(SecondType));

        public static MyTranslatingType ThirdType
            => new MyTranslatingType (nameof(ThirdType));
    }
}

Однако, когда я пытаюсь получить значения из базы данных, Я не могу просто разыграть их или использовать typeof(), потому что они являются свойствами, а не традиционным перечислением / типом.

Я пытался

// error saying it can't convert [PropertyInfo][2] to MyModelClass.MyTranslatingType
MyModelClass.MyTranslatingType myType = typeof(MyModelClass.MyTranslatingType).GetProperty("ThirdType");

// error saying it can't convert string to MyModelClass.MyTranslatingType
MyModelClass.MyTranslatingType myType = (MyModelClass.MyTranslatingType)"ThirdType";

Как я могу разыграть строку "ThirdType" для свойства типа MyModelClass.MyTranslatingType.ThirdType?

Другими словами, я хочу, чтобы myType равнялся MyModelClass.MyTranslatingType.ThirdType для
var myType = (MyModelClass.MyTranslatingType)"ThirdType"

Ответы [ 4 ]

1 голос
/ 13 марта 2020

Я думаю, вы ищете что-то вроде фабричного образца. Вы можете сделать это примерно так:

public class MyTranslatingType
{
    // A dictionary of methods to get the relevant type
    private static Dictionary<string, Func<MyTranslatingType>> _typeFactory = 
        new Dictionary<string, System.Func<MyModelClass.MyTranslatingType>>
        {
            { nameof(FirstType), () => new MyTranslatingType(nameof(FirstType)) },
            { nameof(SecondType), () => new MyTranslatingType(nameof(SecondType)) },
            { nameof(ThirdType), () => new MyTranslatingType(nameof(ThirdType)) },
        };

    // Method to get the type required
    public static MyTranslatingType GetMyTranslatingType(string type)
    {
        if (_typeFactory.TryGetValue(type, out var getType))
        {
            return getType();
        }

        throw new ArgumentOutOfRangeException(nameof(type), $"Cannot get type for {type}");
    }
}

И вы используете это так:

var myType = MyModelClass.MyTranslatingType.GetMyTranslatingType("FirstType");

Этот метод чище, чем ваш, так как у нас больше нет кучки публикаций c stati c методы для получения типов.

Вот полная версия, использующая const s вместо свойств:

public class MyTranslatingType
{
    private const string FirstType = "FirstType";
    private const string SecondType = "SecondType";
    private const string ThirdType = "ThirdType";

    private MyTranslatingType(string value) { Value = value; }

    public string Value { get; set; }

    // A dictionary of methods to get the relevant type
    private static Dictionary<string, Func<MyTranslatingType>> _typeFactory = 
        new Dictionary<string, System.Func<MyModelClass.MyTranslatingType>>
        {
            { FirstType, () => new MyTranslatingType(FirstType) },
            { SecondType, () => new MyTranslatingType(SecondType) },
            { ThirdType, () => new MyTranslatingType(ThirdType) },
        };

    // Method to get the type required
    public static MyTranslatingType GetMyTranslatingType(string type)
    {
        if (_typeFactory.TryGetValue(type, out var getType))
        {
            return getType();
        }

        throw new ArgumentOutOfRangeException(nameof(type), $"Cannot get type for {type}");
    }
}
1 голос
/ 13 марта 2020

Если вы хотите привести один тип к другому: строка в MyTranslatingType, вам нужен неявный или явный оператор приведения:

public static implicit operator string(MyTranslatingType tp) => tp?.Value;
public static implicit operator MyTranslatingType(string value)
{
    return value switch
    {
        nameof(FirstType) => FirstType,
        nameof(SecondType) => SecondType,
        nameof(ThirdType) => ThirdType,
        _ => new MyTranslatingType(value)
    };
}
  • Обратите внимание, оператор switch равен C# 8. Вы можете обновить использовать традиционный синтаксис переключателя.
0 голосов
/ 13 марта 2020

используя Систему; using System.Reflection;

пространство имен ConsoleApp1 {

// Outer class 
public class Outer_class
{

    // Method of outer class 
    public void method1()
    {
        Console.WriteLine("Outer class method");
    }

    // Inner class 
    public class Inner_class
    {

        private Inner_class(string value) { Value = value; }

        public string Value { get; set; }

        public static Inner_class FirstType => new Inner_class(nameof(FirstType));


    }
}

class Program
{
    private const string Name = "FirstType";

    static void Main(string[] args)
    {
        PropertyInfo obj = typeof(Outer_class.Inner_class).GetProperty(Name);

        Console.WriteLine(obj.Name);

        Console.WriteLine(obj.PropertyType);


    }
}
0 голосов
/ 13 марта 2020

typeof(MyModelClass.MyTranslatingType).GetProperty("ThirdType") вернуть PropertyInfo.

Чтобы получить значение:

var myType = (MyModelClass.MyTranslatingType)typeof(MyModelClass.MyTranslatingType).GetProperty("ThirdType").GetGetMethod().Invoke(null, null);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...