C # - определить словарь универсальных функций - PullRequest
0 голосов
/ 30 марта 2019

Как определить словарь, который отображает тип в функцию, которая принимает этот тип в качестве ввода

Что-то вроде:

var stringifiers = new Dictionary<Type, Func<T, string>> {
        { typeof(string), s => s},
        { typeof(float), f => f.ToString()},
        { typeof(bool), b => b.ToString()},
    };

использование:

stringifiers[bar.getType()](bar)

Приведенное выше определение словаря явно не компилируется

Ответы [ 2 ]

3 голосов
/ 30 марта 2019

Если вы не застряли в словаре и хотите установить взаимно-однозначное соотношение между типом и функцией, вы можете использовать общие статические переменные для хранения и извлечения функций и обеспечения безопасности типов в процессе.

"Магия" происходит в StringInternal<T>. Поскольку StringInternal<string>.Stringify - это переменная, отличная от StringInternal<float>.Stringify, вы можете сохранить Func в этой статической переменной и получить к ней доступ, используя тип.

Класс Stringifier - это неуниверсальный класс с универсальными функциями, так что мы можем использовать вывод типов, упрощая наш синтаксис вызова.

public static class Stringifier
{
    public static void Set<T>(Func<T, string> func)
    {
        StringifierInternal<T>.Stringify = func;
    }

    public static string Stringify<T>(T value)
    {
        return StringifierInternal<T>.Stringify(value);
    }

    private static class StringifierInternal<T>
    {
        public static Func<T, string> Stringify { get; set; }
    }
}

Использование:

Stringifier.Set<string>(v => v + "stringified");
Stringifier.Set<float>(v => v.ToString() + "floatstringified");
Stringifier.Set<bool>(v => v ? "it's twoo" : "not twoo");

Console.WriteLine(Stringifier.Stringify("X"));
Console.WriteLine(Stringifier.Stringify((float)17));
Console.WriteLine(Stringifier.Stringify(true));

Выход:

Xstringified
17floatstringified
it's twoo
2 голосов
/ 30 марта 2019

Попробуйте этот класс:

public class Stringifier
{
    private Dictionary<Type, Delegate> _store
        = new Dictionary<Type, Delegate>();

    public void Store<T>(Func<T, string> value)
    {
        _store[typeof(T)] = value;
    }

    public Func<T, string> Fetch<T>()
    {
        return (Func<T, string>)_store[typeof(T)];
    }

    public string Fetch<T>(T value)
    {
        return this.Fetch<T>().Invoke(value);
    }

    public string Fetch(Type type, object value)
    {
        return (string)
        (
            typeof(Stringifier)
                .GetMethods()
                .Where(x => x.Name == "Fetch")
                .Where(x => x.IsGenericMethod)
                .Where(x => x.ReturnType == typeof(string))
                .Select(x => x.MakeGenericMethod(type))
                .First()
                .Invoke(this, new [] { value })
        );
    }       
}

Тогда вы можете сделать это:

var stringifier = new Stringifier();

stringifier.Store<string>(s => $"!{s}!");
stringifier.Store<float>(f => f.ToString());
stringifier.Store<bool>(b => b.ToString());

var bar = "XXX";

var value = stringifier.Fetch(bar.GetType(), bar);

Console.WriteLine(value);   

Я получаю вывод !XXX!.

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