我有一个项目,我们有自己的客户注册和帐户管理系统,但应用程序的某些元素链接到第三方服务。这些服务具有共同的功能,在他们自己的数据库中创建一个帐户,但底层实现将与如何与第三方服务进行交互不同。
到目前为止我所做的是创建一个实现ICustomerRepository的CustomerRepository。这包含我们自己的所有特定要求。 ICustomerRepository还有所有第三方将拥有的常用方法的定义,但这些方法在CustomerRepository类中设置为virtual,如果调用它们则抛出异常,要求您在第三方类中实现它们。
然后,我有:
ThirdPartyACustomer : CustomerRepository, IThirdPartyACustomer
ThirdPartyBCustomer : CustomerRepository
正如您可能猜到的那样,这两个子类都继承并覆盖虚方法,但ThirdPartyACustomer除外,它还实现了特定于该特定类型的第三方用户的其他方法(例如,可能存在用户可以编辑与第三方B不提供的第三方A相关的特定功能。
现在,除此之外,我的问题的真正基础是:
我的应用程序中的某些进程(控制器)可以毫无问题地使用CustomerRepository,因为它们只需要我们的核心功能。
应用程序中的其他进程需要传递特定类型的ICustomerRepository。调用在CustomerRepository中定义为虚拟的方法的任何东西都需要传递ThirdPartyACustomer或ThirdPartyBCustomer,以便调用正确的实现。
最初在这种控制器的初始化中,我会做类似的事情:
public RegistrationController()
{
ICustomerRepository _customerRepository = GetCustomerRepository();
}
其中GetCustomerRepository()有一些逻辑可以确定使用哪种类型的ThirdParty,例如基于子域。
现在,我在想的是我通过创建一个自定义属性来改进这一点:
[ThirdPartyDependent]
class RegistrationController
{
public RegistrationController(ICustomerRepository customerRepository)
{
_customerRepository = customerRepository;
}
}
并将customerRepository参数的数量移动到该属性中,例如GetCustomerRepository中的逻辑会在那里发生。
我很确定这样的东西是可行的,似乎对测试目的有意义,但不太确定我应该用什么谷歌搜索,或者是否有更好的方法来做事,所以寻找一些指导来自对MVC更有经验的人。
答案 0 :(得分:0)
这是DI框架的责任。例如,Ninject允许您在配置依赖项时访问HttpContext,因此您可以根据某些HttpContext值选择正确的实现。例如:
kernel.Bind<ICustomerRepository>().ToMethod(ctx =>
{
if (HttpContext.Current.... Test something on the request or domain or whatever)
{
return new ThirdPartyACustomer();
}
return ThirdPartyBCustomer();
});
然后你的控制器当然是完全不可知的。控制器应该关心的是它会注入一些符合给定合同的存储库:
public class RegistrationController: Controller
{
private readonly ICustomerRepository _customerRepository;
public RegistrationController(ICustomerRepository customerRepository)
{
_customerRepository = customerRepository;
}
}