Выполните «задачу» с помощью перечисления и поля, проверив тип «Т» и автоматически выведя его в задачу - PullRequest
0 голосов
/ 01 октября 2018

Я столкнулся с проблемой, которую не могу решить.У меня есть IReadOnlyList классов, каждый из которых имеет несколько полей.Эти поля имеют имена (имена переменных), идентичные списку перечислений.Подумайте, что для каждого существующего поля также существует перечисление для него с точно таким же именем (поэтому object helloHi имеет эквивалент enum something { helloHi }).

Я пытался сравнить два поляимена.Если они идентичны, выполните для них функцию.Проблема заключается в том, что функция должна вывести T из переменной, и поскольку рефлексия не может извлечь это 'T' без какой-либо формы приведения, она не будет продолжена.

Этокод:

public class Something() {

    [BackgroundTask]
    private void load(Overlay param_1, Config param_2) {
        Children = new Drawable[] // is the IReadOnlyList
        {
            SomethingClass(param_1),
            AnotherClass(param_2)
        }

        performTask(this, param_2);
    }
}

public class Config {

    public void task<U>(SomeEnums se, ValueType<U> value) // do the task
}

public class SomethingClass {

    ValueType<double> someDouble = new ValueType<double>();
    ValueType<int> someInt = new ValueType<int>();

    public SomethingClass(Overlay overlay) //...
}

public enum SomeEnums {
    someDouble,
    someInt,
}

void performTask(Something the_class, Config the_config) {
    // ... for each field within the_class, do (uses reflection)
    field => {
        foreach (SomeEnums enums in Enum.GetValues(typeof(SomeEnums)))
        {
            if (field.Name == enums.ToString()) {
                the_config.task(enums, field.GetValue(null)); // cant infer 'U' from an 'object'
            }
        }
    }
}

Технически, я мог бы просто сделать config.task в классе, где типы известны и видимы, но я бы предпочел автоматизировать его отсюда, чтобы он неКаждый раз, когда создается новая переменная, требуется 2-3 изменения.

Одна из известных мне стратегий заключается в выполнении проверки if в performTask, например:

// performTask, field =>, foreach
{
    if (field.FieldType == ValueType<double>)
        config.task(enums, (ValueType<double>)field.GetValue(null));
} //etc

Однако мне не нравится этот метод.Просто нужно будет вводить все больше и больше проверок, если я когда-либо создаю больше ValueType<> и если они еще не проверяются.Будет ли лучший способ выполнить то, что я хочу?

1 Ответ

0 голосов
/ 01 октября 2018

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

Он использует отражение для получения полей объектов, просмотра имен этих полей (сравнения их со значениями / именами, связанными с типом enum) и сравнения значений.Я делаю сравнение с целым числом 5, но вы можете сравнить с чем угодно (но, похоже, что реализация целочисленного типа IComparable.CompareTo выдает, если она сравнивается с чем-то отличным от int, поэтому я проверяю).Поскольку вы знаете тип всего, это легко проверить (вам не нужно сравнивать с фиксированным Type, вы можете использовать то, что возвращает GetType()).

Я начал с некоторыхвспомогательные типы:

public enum SomeEnums {
    SomeDouble,
    SomeInt,
}

public class Class1 {
    public int SomeInt = 5;
    public double SomeDouble = 3.14;
}

public class Class2 {
    public int SomeInt = 5;
    public double SomeDouble = 6.28;
}

, а затем добавили:

public class EnumFields {

    public List<object> Objects = new List<object> {
        new Class1(),
        new Class2(),
    };

    public void PerformTask () {
        var enumVals = Enum.GetNames(typeof(SomeEnums));
        foreach (var obj in Objects) {
            var objType = obj.GetType();
            var fieldInfos = objType.GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
            //right around here I get lost.  You have a list of objects (which has two instances right now), 
            //What are you comparing, that every field named SomeInt has the same value??
            //Anyway, here's some code that should help you
            foreach (var fieldInfo in fieldInfos) {
                if (enumVals.Contains(fieldInfo.Name)) {
                    var fieldObj = fieldInfo.GetValue(obj);
                    var isSame = false;
                    if (fieldObj.GetType() == typeof(int)) {
                        var comparable = (IComparable)fieldObj;
                        var same = comparable.CompareTo(5);
                        isSame = (same == 0);
                    }
                    Debug.WriteLine($"Field: {fieldInfo.Name} of instance of {obj.GetType().Name} (Value: {fieldObj}) is equal to 5:{isSame}");
                }
            }
        }
    }
}

Когда я создаю экземпляр EnumFields объекта и вызываю PerformTask, я вижу это в выводе:

Field: SomeInt of instance of Class1 (Value: 5) is equal to 5:True
Field: SomeDouble of instance of Class1 (Value: 3.14) is equal to 5:False
Field: SomeInt of instance of Class2 (Value: 5) is equal to 5:True
Field: SomeDouble of instance of Class2 (Value: 6.28) is equal to 5:False

Это должно помочь вам в этом.Я понимаю, что это не отвечает на ваш вопрос.Если бы я смог понять, о чем ты спрашиваешь, это, вероятно, могло бы быть.

...