c# - 当实现如此不同时,依赖注入场景中使用的接口和类的设计过程
问题描述
以从网页中提取数据的服务为例(例如 Mercury https://mercury.postlight.com/web-parser/或 Diffobt https://www.diffbot.com/products/automatic/#article)我想要询问有关如何为依赖注入 (DI)/控制反转 (IoC) 场景构建接口和类实现的问题。
我正在尝试确定如何最好地创建一个IPageExtractor
接口和后续的具体实现MercuryPageExtractor
,并在实际实现完全不同的情况下DiffbotPageExtractor
实现该接口。IPageExtractor
显然,这是首先实现接口的全部要点,但我有一个心理障碍,我需要帮助克服。
例如,Mercury 使用密钥和秘密进行身份验证,而 Diffbot 仅使用令牌。好吧,也许这并没有太大的不同,但我感到困惑的是我必须在界面中适应它,当然界面是最低公分母。例如,我是否会传入一组身份验证数据并让具体实现对其进行排序?
另一个不同之处是 Mercury 返回关于网页的 3 条数据,而 Diffbot 返回 20 条(这在技术上可能不准确,但可能存在差异的示例就是我所得到的)。我将如何设计接口和具体实现来处理这个问题?
最后一个显着的区别是,在每种情况下,成功和失败的构成非常不同,成功或失败返回的消息类型(格式、结构、内容)也有很大差异。
你能帮忙想想这个问题吗?
我在 C#/.NET 中工作,但以独立于语言的方式考虑这一点。
解决方案
让我们看一下接口驱动的抽象工厂的另一个场景
在开始之前,我们需要清楚接口指定了需要做什么,并带有输入和所需输出的微妙指示。也就是说,它并不强制要求输入和输出都需要很好地定义,因为它们本身也可以被视为合同。如果我们不完全清楚输入和输出的结构是什么,我们可以使用标记接口;那些根本没有任何结构的..
假设我们有一个购物车,我们需要提供付款选项。常见的选择是网上银行、信用卡和贝宝。让我们有这个场景的定义
public interface ICustomerAccountInformation { }
public interface IPaymentClient { } // Identifies whom the payment is intended for
public interface ITransactionDetails : IPaymentClient { } // Identifies amount, beneficiary details to be reflected in customer account
public interface IPaymentStatus { }
public interface IPaymentProvider {
IPaymentStatus ProcessPayment(ICustomerAccountInformation customerInfo, ITransactionDetails transaction);
}
public class PayPal : IPaymentProvider {
public IPaymentStatus ProcessPayment(ICustomerAccountInformation customerInfo, ITransactionDetails transaction) {
/* Open paypal's login page,
do its own checks and process payment.
Once successfull, send back to referrer with the payment status
*/
}
public class NetbankingProvider : IPaymentProvider {
public IPaymentStatus ProcessPayment(ICustomerAccountInformation customerInfo, ITransactionDetails transaction) {
/* Redirect to bank selection
redirect to bank's login page,
do its own checks and process payment.
Once successfull, send back to referrer with the payment status
*/
}
在整个流程中,每个提供者都可以自由询问所需的任何信息(有些只是获取凭据,而另一些则要求提供 OTP 作为附加信息)。他们还根据自己的结构返回状态。然而,在逻辑层面上,如果支付成功与否,他们会获取用户的凭据并返回一条消息
您可以将工厂设计为独立于任何其他供应商设计。只需在每个合同上都有标记接口。
在执行 DI 代码(例如NInject)时,使用“ WhenInjectedInto ”或类似构造将正确的实现注入到正在使用的每个提供程序中。您的工厂将根据用户的选择可供使用,而不会影响您的核心业务流程。
DI的主要规则是从核心业务中完全抽象出非核心业务。核心业务不应该关心每个提供商的期望,只是对预期的功能有一个模糊的想法。标记界面最适合此要求,尤其是当您已经开始设计但还不完全清楚时。随着您对所涉及的过程更加清晰,您可以稍后改进标记界面。
如果您需要进一步了解设计,请告诉我。
推荐阅读
- javascript - 当我在 Chrome 中打开一个 THREE.js 应用程序时,我的浏览器拖得很糟糕
- java - 如果返回 Http 401 再次调用 API
- python - Scrapy 如何在 Jupyter notebook 上工作?
- excel - 删除 Excel 中单元格值在其他行中不重复的行
- python - 如何使用`import`调用文件夹中的一组脚本?
- ms-access - 您可以对子表单中的计算字段求和吗?
- json - 如何在pyspark中使用多行选项将数据框保存到json文件中
- javascript - Html/XML 在寻找不应该出现的节点时遇到问题
- ffmpeg - 如何使用ffmpeg在视频上添加水印为gif和文本
- java - Android:在 featureModule 与库模块上导入资源