Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当实现如此不同时,依赖项注入场景中使用的接口和类的设计过程_C#_Dependency Injection_Interface_Inversion Of Control_Concreteclass - Fatal编程技术网

C# 当实现如此不同时,依赖项注入场景中使用的接口和类的设计过程

C# 当实现如此不同时,依赖项注入场景中使用的接口和类的设计过程,c#,dependency-injection,interface,inversion-of-control,concreteclass,C#,Dependency Injection,Interface,Inversion Of Control,Concreteclass,以从网页中提取数据的服务为例(例如Mercury或Diffobt),我想问一个关于如何为依赖注入(DI)/控制反转(IoC)场景构建接口和类实现的问题 我正试图确定如何最好地创建一个IPageExtractor接口,以及后续的具体实现MercuryPageExtractor和DiffbotPageExtractor,它们实现了IPageExtractor接口,因为实际实现是完全不同的 显然,这是实现接口的第一步,但我有一个心理障碍,我需要帮助克服 例如,Mercury使用密钥和密码进行身份验证,

以从网页中提取数据的服务为例(例如Mercury或Diffobt),我想问一个关于如何为依赖注入(DI)/控制反转(IoC)场景构建接口和类实现的问题

我正试图确定如何最好地创建一个
IPageExtractor
接口,以及后续的具体实现
MercuryPageExtractor
DiffbotPageExtractor
,它们实现了
IPageExtractor
接口,因为实际实现是完全不同的

显然,这是实现接口的第一步,但我有一个心理障碍,我需要帮助克服

例如,Mercury使用密钥和密码进行身份验证,而Diffbot仅使用令牌。好吧,也许这没什么不同,但我感到困惑的是,我必须在接口中考虑到这一点,当然,接口是最低公分母。例如,我是否会传入一组auth数据,并让具体的实现对其进行排序

另一个不同之处是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)时,使用“WhenInjectedTo”或类似的构造将正确的实现注入到所使用的每个提供程序中。根据用户的选择,您的工厂将可供使用,而不会影响您的核心业务流程

DI的主要规则是将非核心业务从核心业务中完全抽象出来。核心业务不应该关心每个提供商的期望值,而应该对期望的功能有一个模糊的概念。标记接口最适合这个需求,特别是当您已经开始设计但还不完全清楚时。随着所涉及的过程更加清晰,您可以稍后改进标记接口


如果您需要进一步明确设计,请告诉我。

您是否正在尝试将这两个实现整合到一个类/接口中?所以你不必同时注入这两个?不,我知道我将有两个具体的实现,正如我上面所说的。我需要帮助克服一个心理障碍,那就是如何为实现方式截然不同的事物设计一个接口。我的问题可能比你想的更基本。我不确定你是不是投了反对票,但我想请你耐心一点,因为我想知道怎么问这个问题。如果我投了你的反对票,你通常会知道的。你有什么理由想把它们组合成一个界面吗?你能从中看到什么价值?通过回答这个问题,每个人都能更好地了解你为什么要这么做,你的期望是否合理,合同可能看起来是什么样子。我认为Mercury和Diffbot都提供相同的基本服务——它们解析网页并提取我需要的数据(一个干净的页面)。它们是两种实现。我想注入我需要的特定实现。我认为这是DI的基础,在运行时以松散耦合的方式替换不同的实现。
例如,Mercury使用密钥和密码进行身份验证,而Diffbot只使用令牌。
IoC容器(构造函数注入)应该向他们提供他们需要的任何东西。打电话的人不需要知道区别。