Пишу fluent интерфейс, но возникла проблема
public interface IValidatorExecutorBuilder<T>
{
IValidatorExecutorBuilder<T> WithAsyncCallback(Func<T, CancellationToken, Task> callback);
IValidatorExecutorBuilder<T, TResult>
WithAsyncCallback<TResult>(Func<T, CancellationToken, Task<TResult>> callback);
ActionResult Execute();
}
public interface IValidatorExecutorBuilder<T, TResult> : IValidatorExecutorBuilder<T>
{
// вот тут компилятор ругается на то, что должно быть слово new
ActionResult<TResult> Execute();
}
в данном примере
T
это модель, которая должна быть в обоих типах интерфейсов
т.е тут получается наследование дженерика, которое расширяется на еще один тип
ну похоже на
Task
и
Task<TResult>
.
так вот я что-то думаю что хожу вокруг да около, а вопрос примерно такой
как сделать так, что если я после записи вот такой цепочки
.WithAsyncCallBack((m, t) => Task.FromResult(1)))
.Execute()
на выходе получал не
ActionResult
, а
ActionResult<int>
? Ну т.е чтобы метод брался с
IValidatorExecutorBuilder<T, TResult>
и соответственно наоборот, если был передан в колбеке просто
Task
вопрос глупый, но что-то вообще не вдупляю. все смешалось
т.е тут по большей части переопределение не типа, а возвращаемой сигнатуры, т.е либо non-generic class, либо generic, унаследованного от non-generic
p.s
вот так выглядит вполне жизнеспособно
public interface IValidatorExecutorBuilder<T>
{
IValidatorExecutorBuilder<T> WithAsyncCallback(Func<T, CancellationToken, Task> callback);
IValidatorExecutorBuilder<T, TResult> WithAsyncCallback<TResult>(Func<T, CancellationToken, Task<TResult>> callback);
ActionResult Execute();
}
public interface IValidatorExecutorBuilder<T, TResult>
{
ActionResult<TResult> Execute();
}
но это вариант без наследования интерфейса, плохо или хорошо - хз.
ps2
изменил на вот такую схему
public interface IValidatorExecutorBuilder<T>
{
IValidatorExecutor<T> WithAsyncCallback(Func<T, CancellationToken, Task> callback);
IValidatorExecutor<T, TResult>
WithAsyncCallback<TResult>(Func<T, CancellationToken, Task<TResult>> callback);
}
public interface IValidatorExecutor<T>
{
IValidatorExecutor<T> ContinueWith(Func<T, CancellationToken, Task> callback);
ActionResult Execute();
}
public interface IValidatorExecutor<T, TResult>
{
ActionResult<TResult> Execute();
}
тогда в таком случае будет доступно всего 2 способа использования
return await _validatorResolverService.ForModel(model)
.WithModelState(ModelState)
.WithAsyncCallback(async (m, t) => await _accountService.RevokeSession(m, t))
.ContinueWith()
.ContinueWith();
//etc
return await _validatorResolverService.ForModel(model)
.WithModelState(ModelState)
.WithAsyncCallback(async (m, t) => await Task.FromResult(1))
.Execute();
// only 1 callback
какой из этих способов предложенных ближе к истине?