К 1: Да (Вы также можете параметризовать bool и string):
Func<T, bool> Compose<T>(Func<T, string> source, Func<string, bool>map)
{
return x => map(source(x));
}
To 2: Да, но сначала нужно скомпилировать выражение:
Func<T, bool> Compose<T>(Expression<Func<T, string>> source, Func<string, bool> map)
{
return x => compose(source.Compile(), map)
}
.Compile
скомпилирует выражение в динамический метод CLR, который вы можете вызвать с возвращенным делегатом.
Вы можете использовать этот код так:
Func<int, string> ts = i => i.ToString();
var result = Compose(ts, string.IsNullOrEmpty);
Кстати, в этом случае вы действительно должны написать функцию более высокого порядка. То, что вы делаете здесь (алгебраически) - это сочинение моноидов. Помните функция композиции ? f . g := f(g(x))
это то, что вы делаете здесь.
Думайте об источнике как g:A->B
и отображайте как f:B->C
(где A, B и C - наборы), поэтому результат f . g
равен h:A->C
. Кстати, оператор .
часто встроен в функциональные языки программирования, такие как Haskell, и выполняет те же функции, что и ваша функция compose
(но с более чистым синтаксисом).