基础设施——同步和异步接口和实现?
Infrastructure - both sync & async interface & implementation?
在实现 library/infrastructure 时,这个 API 的用户想要同步和异步使用代码,我读到混合同步和异步不是一个好主意(例如同步实现包括等待异步实现)。
显然同步和异步实现应该分开。
是否有一种优雅的方法来避免同步和异步实现的代码(或更准确地说 "flow")重复,这显然会向下扩展到整个调用层次结构?
interface IMyInterface
{
void Foo();
Task FooAsync();
}
class MyImplementation1 : IMyInterface
{
public void Foo()
{
OtherMethod1();
OtherMethod2();
OtherMethod3();
OtherMethod4();
}
public async Task FooAsync()
{
await OtherMethod1Async();
await OtherMethod2Async();
await OtherMethod3Async();
await OtherMethod4Async();
}
private void OtherMethod1() { /* may contain other sync calls */ }
private void OtherMethod2() { /* may contain other sync calls */ }
private void OtherMethod3() { /* may contain other sync calls */ }
private void OtherMethod4() { /* may contain other sync calls */ }
private async Task OtherMethod1Async() { /* may contain other async calls */ }
private async Task OtherMethod2Async() { /* may contain other async calls */ }
private async Task OtherMethod3Async() { /* may contain other async calls */ }
private async Task OtherMethod4Async() { /* may contain other async calls */ }
}
根据您的逻辑,您仍然可以分享一些逻辑。但有不同,就应该有所不同。
如果有帮助,您可以使用模板系统(如 T4)生成代码。
When implementing a library/infrastructure, and the user of this API would want to use the code both synchronously & asynchronously
理想情况下,您库中的每个 API 应该自然同步或自然异步。我建议只暴露最自然的 API。即,如果您的库需要执行 I/O,它可以选择仅公开异步 API.
Is there an elegant way to avoid code (or more accurately "flow") duplication for sync & async implementations, which would obviously bubble down to the whole call hierarchy?
我还没有找到理想的解决方案。我最接近的是 boolean argument hack,其中异步和同步 API 都转发到采用 bool sync
参数的内部方法。此内部方法具有异步签名(返回 Task
/Task<T>
),但如果 sync
是 true
,它总是 returns 已完成的任务。
最后看起来像这样:
interface IMyInterface
{
void Foo();
Task FooAsync();
}
class MyImplementation1 : IMyInterface
{
public void Foo() => Foo(sync: true).GetAwaiter().GetResult();
public Task FooAsync() => Foo(sync: false);
private async Task Foo(bool sync)
{
// Pass `sync` along to all methods that can be sync or async.
await OtherMethod1(sync);
await OtherMethod2(sync);
await OtherMethod3(sync);
await OtherMethod4(sync);
}
private async Task OtherMethod1(bool sync)
{
// When you have to choose sync/async APIs of other classes, then choose based on `sync`.
if (sync)
Thread.Sleep(1000); // synchronous placeholder
else
await Task.Delay(1000); // asynchronous placeholder
}
}
在实现 library/infrastructure 时,这个 API 的用户想要同步和异步使用代码,我读到混合同步和异步不是一个好主意(例如同步实现包括等待异步实现)。
显然同步和异步实现应该分开。
是否有一种优雅的方法来避免同步和异步实现的代码(或更准确地说 "flow")重复,这显然会向下扩展到整个调用层次结构?
interface IMyInterface
{
void Foo();
Task FooAsync();
}
class MyImplementation1 : IMyInterface
{
public void Foo()
{
OtherMethod1();
OtherMethod2();
OtherMethod3();
OtherMethod4();
}
public async Task FooAsync()
{
await OtherMethod1Async();
await OtherMethod2Async();
await OtherMethod3Async();
await OtherMethod4Async();
}
private void OtherMethod1() { /* may contain other sync calls */ }
private void OtherMethod2() { /* may contain other sync calls */ }
private void OtherMethod3() { /* may contain other sync calls */ }
private void OtherMethod4() { /* may contain other sync calls */ }
private async Task OtherMethod1Async() { /* may contain other async calls */ }
private async Task OtherMethod2Async() { /* may contain other async calls */ }
private async Task OtherMethod3Async() { /* may contain other async calls */ }
private async Task OtherMethod4Async() { /* may contain other async calls */ }
}
根据您的逻辑,您仍然可以分享一些逻辑。但有不同,就应该有所不同。
如果有帮助,您可以使用模板系统(如 T4)生成代码。
When implementing a library/infrastructure, and the user of this API would want to use the code both synchronously & asynchronously
理想情况下,您库中的每个 API 应该自然同步或自然异步。我建议只暴露最自然的 API。即,如果您的库需要执行 I/O,它可以选择仅公开异步 API.
Is there an elegant way to avoid code (or more accurately "flow") duplication for sync & async implementations, which would obviously bubble down to the whole call hierarchy?
我还没有找到理想的解决方案。我最接近的是 boolean argument hack,其中异步和同步 API 都转发到采用 bool sync
参数的内部方法。此内部方法具有异步签名(返回 Task
/Task<T>
),但如果 sync
是 true
,它总是 returns 已完成的任务。
最后看起来像这样:
interface IMyInterface
{
void Foo();
Task FooAsync();
}
class MyImplementation1 : IMyInterface
{
public void Foo() => Foo(sync: true).GetAwaiter().GetResult();
public Task FooAsync() => Foo(sync: false);
private async Task Foo(bool sync)
{
// Pass `sync` along to all methods that can be sync or async.
await OtherMethod1(sync);
await OtherMethod2(sync);
await OtherMethod3(sync);
await OtherMethod4(sync);
}
private async Task OtherMethod1(bool sync)
{
// When you have to choose sync/async APIs of other classes, then choose based on `sync`.
if (sync)
Thread.Sleep(1000); // synchronous placeholder
else
await Task.Delay(1000); // asynchronous placeholder
}
}