2

我是一名程序员,正在使用 .Net 4.0 进行项目,并试图找出将松散耦合和可扩展设计与同一逻辑操作有时可能异步执行且有时仅同步执行的事实相结合的最佳方法(每个实现支持异步也支持同步,但不是相反)。在这个项目中,每一个这样的逻辑操作都由一个接口表示(松耦合和可扩展性要求很高)。让我们将我的问题集中在一个特定的界面上:IDataDictLoader. 该接口负责加载一个名为DataDict. 此接口有两种可能的实现:一种调用它使用本地 dll 并同步LocalDataDictLoader执行操作(返回DataDict),另一个调用WebServiceDataDictLoader它使用 Web 服务并异步(返回Task<DataDict>或同步执行操作。配置文件中的值确定要创建的实现 - 如果值为“Local”,则LocalDataDictLoader创建,如果值为“WebService”,则WebServiceDataDictLoader创建。创建部分在函数中使用由约定引导的反射IDataDictLoader CreateLoader(string configValue)。调用该函数并使用接口的代码事先并不知道实现是什么,即使它想知道它也无法访问配置值。问题是如何设计界面?截至目前,我想到了许多选择:

  1. 接口上有两种方法,一种是同步的,一种是异步的,并且LocalDataDictLoader在同步版本中有异步包装器。正如 Stephen Toub在这里所建议的那样,这不是推荐的解决方案。
  2. 按照 Josh 在他的 IIMViewModelDL 示例中对问题的回答所建议的去做,这样接口将有一个带有回调参数的 void 方法。虽然该解决方案将从客户端代码中隐藏实现细节,但在我看来,它具有异步调用语义,使用回调。在我看来,这相当于始终返回 aTask<DataDict>并让同步实现同步加载,然后使用TaskCompletionSource<DataDict>. 出于同样的原因,这与选项 1 是错误的。
  3. 将接口拆分为两个接口:IDataDictLoader用于同步、IAsyncDataDictLoader : IDataDictLoader用于异步和同步。该解决方案为客户端代码提供了有关操作是否可以异步执行的知识,它不会“撒谎”其性质。现在的缺点是客户端代码,称为CreateLoader(string configValue),现在必须使用 as/is 条件编码样式来知道它收到的IDataDictLoader实际上是一个IAsyncDataDictLoader还是不是。

那么,您将如何在松散耦合和可扩展性需求之间取得平衡,同时揭示配置实现是否支持异步的真实性质?

4

1 回答 1

0

我认为你应该做的是让你的界面异步。如果一个实现是同步的,它可以返回一个已经完成的Task。这样,您的消费代码不需要了解实现,并且可以将其视为异步的。

于 2013-05-30T22:36:37.137 回答