Это кажется довольно сложным, чтобы спросить, и хотя решение кажется простым, ошеломляющая часть делегатов внутри делегатов, возвращенных еще большим количеством делегатов, заставила мой мозг взорваться сам по себе.
Без лишних слов объясню:
Сценарий состоит в том, что у вас есть делегаты преобразования (Func[A, B]) и поведение преобразования (Func[A, Func[Func[A, B], B]]).
Идея состоит в том, что вокруг данного перевода у вас будет определенный набор поведений, которые оборачивают вызов в перевод, т. е. что они берут А, не стесняются делать с ним все, что хотят, передают это следующему. поведение, при этом имея возможность изменить возвращаемое значение (B).
Вероятно, есть какая-то монада, которая идеально описывает это, но, возможно, некоторый код поможет больше, чем что-либо еще.
Жертвы:
public class B
{
}
public class A
{
}
Делегат поведения
public delegate Func<Func<A, B>, B> TranslationBehavior(A input);
Функция, которая должна связать их вместе и вернуть Func, которая позволяет передать функцию перевода и получить новую функцию перевода, которая обернута поведением.
static Func<Func<A, B>, Func<A, B>> Chain(IEnumerable<TranslationBehavior> behaviors)
{
throw new NotImplementedException();
}
сценарий использования
static void Main(string[] args)
{
var behaviors = new[]
{
(TranslationBehavior) (inp => next => next(inp)),
(TranslationBehavior) (inp => next => next(inp)),
(TranslationBehavior) (inp => next => next(inp)),
};
var input = new A();
var chained = Chain(behaviors);
var output = chained(a => new B());
}
В примере кода реализации поведения ничего не делают, а вызывают следующее поведение, а наша реализация перевода просто возвращает новый код B.
Функция «цепочка» — это проблемная функция, возможность связать поведение вместе ускользнула от меня, но чтобы доказать себе, что это действительно должно работать, я жестко запрограммировал наивное решение, которое специально связывает три поведения вместе:
static Func<Func<A, B>, Func<A, B>> Chain(IEnumerable<TranslationBehavior> behaviors)
{
var behavior1 = (TranslationBehavior)null;
var behavior2 = (TranslationBehavior)null;
var behavior3 = (TranslationBehavior)null;
return translation => input =>
behavior1(input)(transformed1 =>
behavior2(transformed1)(transformed2 =>
behavior3(transformed2)(translation)
)
);
}
Это работает, но очевидно; совсем бесполезно.
Любая помощь по этому поводу была бы действительно полезной, и любая информация о том, является ли это известным шаблоном или монадой, была бы действительно интересной, я не думаю, что этот код далеко не обобщаемый.
Заранее спасибо, Стивен.