52

我有一个应用程序。此应用程序使用接口来访问数据库。这个接口可以被很多类实现。例如,一个使用 EF 4.4,但其他类可以使用更高效的 EF5。将来我可能会使用 EF6,因为它使用异步方法。在此示例中,所有方法都使用 EF,但也许其他选项可以使用其他方式。

应用程序编码一次,使用接口,并根据配置文件,使用一个实现或另一个,所以我只需要在一个地方修改代码,构造函数,在类的实例化中添加新选项分配给接口。

目前类的所有方法都不是async,但是将来如果我使用EF6我想使用异步方法,所以我不知道使用EF6并实现接口的类是否可以使用async方法。

对于 EF6 的异步方法,我会使用 async/awiat 模式,因此在我的类的方法中我需要使用 async 属性。这让我await在调用 EF6 的异步方法时可以使用关键字。

但是这个类可以实现第一次用于同步方法的接口吗?

有没有什么方法可以在主应用程序中使用许多实现而不需要修改代码?一些实现将使用异步方法,而其他实现将是同步的。

4

1 回答 1

64

async不是签名的一部分,所以你实际上不需要关心实现接口的方法是否是async,你只需要关心属性的类型,返回类型,名称方法和可访问性。

真正的区别在于您的async方法将需要返回 aTask或 a Task<T>,而非异步方法最有可能当前直接返回void或某种类型T

如果您想“面向未来”您的应用程序,一种选择是确保您的所有接口都返回Task,或者Task<T>对于您的 EF4/EF5 实现,您将结果包装在一个已完成的任务中,即使它们是同步执行的。

Task.FromResult已在 .NET 4.5 中添加,但如果您没有它,您可以轻松编写自己的代码:

public static Task<T> FromResult<T>(T result)
{
    var tcs = new TaskCompletionSource<T>();
    tcs.SetResult(result);
    return tcs.Task;
}

您还可以编写一个CompletedTask简单地返回已完成任务的方法:(出于效率原因,它缓存单个任务。)

private static Task _completedTask;
public static Task CompletedTask()
{
    return _completedTask ?? initCompletedTask();
}

private static Task initCompletedTask()
{
    var tcs = new TaskCompletionSource<object>();
    tcs.SetResult(null);
    _completedTask = tcs.Task;
    return _completedTask;
}

这两种方法将简化让您的所有方法返回某种类型的过程Task,尽管这样做会使您的代码有点混乱,直到您能够使用 C# 5.0 来获得await结果。

于 2012-11-26T21:47:17.267 回答