Dan*_*rth 10 .net c# architecture dependency-injection
我有这样的界面ITradingApi:
public interface ITradingApi
{
IOrder CreateOrder(...);
IEnumerable<Symbol> GetAllSymbols();
// ...
}
Run Code Online (Sandbox Code Playgroud)
这是交易软件供应商的不同API的外观.我的视图模型在其构造函数中依赖于此交易API:
public class MainViewModel
{
public MainViewModel(ITradingApi tradingApi) { /* ... */ }
// ...
}
Run Code Online (Sandbox Code Playgroud)
我使用Ninject作为IoC容器,因此我将创建一个我的视图模型的实例,如下所示:
var vm = kernel.Get<MainViewModel>();
Run Code Online (Sandbox Code Playgroud)
现在,我的问题:
执行ITradingApi可能需要额外的参数才能工作.
例:
本着不允许不完整对象的精神,我将这些作为参数添加到具体实现的构造函数中.
现在,我不确定,这将如何运作.显然,这些附加参数不属于接口,因为它们特定于每个实现.
另一方面,这些附加参数需要由最终用户输入然后传递给实现ITradingApi,这意味着用户ITradingApi需要对具体实现有深入了解.
如何解决这个难题?
更新:
一种方法可能是创建一个ITradingApiProvider公开所需参数列表.View可以自动为这些参数创建一个输入表单,该表单将数据绑定到参数中ITradingApiProvider.现在,当ITradingApi从提供程序请求实例时,它可以使用这些参数来创建具体实现的实例.显然执行ITradingApiProvider和ITradingApi紧密耦合,但我认为只要每个实现ITradingApi都带有相应的实现,这不是问题ITradingApiProvider.
根据目前提供的信息,我想指出一两件事:
首先,具体的配置值是否在组合时提供,或者在运行时作为用户输入真正首先可用,会产生巨大的差异。只要它们可以在组合时解决,事情就很容易,因为您可以简单地从环境中读取值并将它们提供给适当的构造函数。因此,对于这个答案的其余部分,我将假设事情要困难得多,并且您实际上需要在运行时从用户那里获取这些值。
我宁愿对实际发生的情况进行建模,而不是尝试提出通用配置 API。在这种情况下,我觉得我们正在从用户那里收集配置值,那么为什么不明确地对此进行建模呢?
产品交易员
定义一个这样的接口:
public interface ITradingApiTrader
{
ITradingApi Create(Type apiType);
}
Run Code Online (Sandbox Code Playgroud)
这里,假设apiType可以转换为 ITradingApi,但这不能由编译器强制执行。(我将其称为“交易者”的原因是因为这是产品交易者模式 (PLoPD 3) 的变体。)
这和以前有什么不同?
那么,您可以通过显示每种类型的 ITradingApi 的用户界面来实现Create 方法。每个具体用户界面都会收集其自己的具体 ITradingApi 实现所需的值,然后返回正确配置的实例。
如果您在编译时知道具体类型,其他变体包括:
public interface ITradingApiTrader
{
ITradingApi CreateMT4TradingApi();
ITradingApi CreateFooTradingApi();
ITradingApi CreateBarTradingApi();
// etc.
}
Run Code Online (Sandbox Code Playgroud)
也许你也可以这样做(虽然我还没有尝试编译这个):
public interface ITradingApiTrader
{
ITradingApi Create<T>() where T : ITradingApi;
}
Run Code Online (Sandbox Code Playgroud)
另请注意,您不需要基于类型定义第一个 ITradingApiTrader 的 Create 方法 - 任何标识符(例如枚举或字符串)都可以代替。
游客
如果 ITradingApi 集在设计时是(有限且)已知的,则访问者设计模式也可能提供替代方案。
如果您使用访问者,则可以使 Visit 方法显示适当的用户界面,然后使用从用户界面收集的值来创建适当的 ITradingApi 实例。
基本上,这只是之前“解决方案”的变体,其中产品交易者作为访问者实现。