Как определить поле гибкого делегата с несколькими необязательными параметрами? - PullRequest
1 голос
/ 15 марта 2019

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

Моя цель - создать удобный для пользователя класс событий, в который пользователи смогут добавлять события с помощью XML-сериализации (эта часть хороша). Поэтому я стараюсь сделать вещи максимально простыми и общими. Я получил несколько условных методов в различных классах, таких как

public class Person
{
    static bool IsOlderThan(int age) {/*...*/}
}

public class Faction
{
    static bool HasRelationMoreThan(Faction faction,float value) {/*...*/}
}

и так далее ...

Я должен определить параметр Func <> или другой делегат, который может принимать эти методы с разным набором параметров вместо определения отдельного поля для каждого из них. TL; DR: мне нужен тип делегата, который принимает любой метод в качестве значения.

Есть ли способ создать гибкую, общую ссылку на метод, подобную этой?

1 Ответ

1 голос
/ 15 марта 2019

Посмотрите на класс MulticastDelegate. Это базовый класс для всех делегатов. Но будь осторожен. MulticastDelegates вызываются через DynamicInvoke (), который работает медленнее, чем Invoke (). Кроме того, вам также необходимо контролировать количество и типы параметров, передаваемых в DynamicInvoke (), поскольку это может привести к ошибкам во время выполнения.

private void TestMulticastDelegate()
{
    Func<int, bool> function1 = IntToBool;
    Func<string, bool> function2 = StringToBool;
    Func<int, string, bool> function3 = IntAndStringToBool;

    int intArg = 1;
    string stringArg = "someString";

    MulticastDelegate d;

    d = new Func<int, bool>(IntToBool);
    bool res1 = d.DynamicInvoke(intArg).Equals(function1(intArg)); // always true

    d = new Func<string, bool>(StringToBool);
    bool res2 = d.DynamicInvoke(stringArg).Equals(function2(stringArg)); // always true

    d = new Func<int, string, bool>(IntAndStringToBool);
    bool res3 = d.DynamicInvoke(intArg, stringArg).Equals(function3(intArg, stringArg)); // always true
}

private bool IntToBool(int i)
{
    return i == 0;
}

private bool StringToBool(string s)
{
    return string.IsNullOrEmpty(s);
}

private bool IntAndStringToBool(int i, string s)
{
    return i.ToString().Equals(s, StringComparison.OrdinalIgnoreCase);
}
...