用于流畅API的类型推断

D.R*_*.R. 12 c# generics fluent-interface fluent

我有以下扩展方法:

public static IFoo Foo(this IFluentApi api, Action action);

public static IFoo<TResult> Foo<TResult>(
    this IFluentApi api, Func<TResult> func);

public static IBar Bar(this IFoo foo);

public static void FooBar(this IBar bar, Action action);

public static void FooBar<TResult>( // <- this one cannot work as desired 
    this IBar bar, Action<TResult> action);
Run Code Online (Sandbox Code Playgroud)

通用接口始终从其对应的非通用接口派生.

不幸的是,为了使这项工作:

api.Foo(x => ReturnLong())
   .Bar()
   .FooBar(x => ...); // x should be of type long
Run Code Online (Sandbox Code Playgroud)

我还需要实现以下扩展方法:

public static IBar<TResult> Bar<TResult> (this IFoo<TResult> foo);
Run Code Online (Sandbox Code Playgroud)

并将上述最后一个扩展方法更改为:

public static void FooBar<TResult>(
    this IBar<TResult> bar, Action<TResult> action);
Run Code Online (Sandbox Code Playgroud)

正如我其实不仅Bar()之间Foo()以及FooBar()但是方法很长的链我将有巨大的额外的实施成本.

有没有办法避免这个问题并"神奇地"转发TResult通用参数?

编辑:

不丢失类型推断!

SLu*_*k49 4

假设您能够从 an 转到IFoo<TResult>anIFoo并且您的方法链不关心TResult您可以通过将用法更改为类似以下内容来保存一些实现:

api.Foo(x => ReturnLong())
   .Bars(foo=>foo.Bar1() //where foo is an IFoo
                 .Bar2()
                 .Bar3()
                 ...
    )
   .FooBar(x => ...);
Run Code Online (Sandbox Code Playgroud)