C# 具有非依赖参数的构造函数注入
我有一个接口C# 具有非依赖参数的构造函数注入,c#,.net,architecture,dependency-injection,C#,.net,Architecture,Dependency Injection,我有一个接口ITradingApi如下: public interface ITradingApi { IOrder CreateOrder(...); IEnumerable<Symbol> GetAllSymbols(); // ... } 我将Ninject用作IoC容器,因此我将创建视图模型的一个实例,如下所示: var vm = kernel.Get<MainViewModel>(); public interface ITradin
ITradingApi
如下:
public interface ITradingApi
{
IOrder CreateOrder(...);
IEnumerable<Symbol> GetAllSymbols();
// ...
}
我将Ninject用作IoC容器,因此我将创建视图模型的一个实例,如下所示:
var vm = kernel.Get<MainViewModel>();
public interface ITradingApiTrader
{
ITradingApi Create(Type apiType);
}
var vm=kernel.Get();
现在,我的问题是:
ITradingApi
的实现可能需要额外的参数才能工作。例如:
- 一个供应商的API在内部使用TCP/IP,所以我需要一个主机名和一个端口李>
- 另一个供应商使用COM对象。这里我不需要任何信息李>
- 第三个供应商需要帐户的用户名和密码
另一方面,这些附加参数需要由最终用户输入,然后传递给
ITradingApi
的实现,这意味着ITradingApi
的用户需要了解具体实现。如何解决这一困境 更新:
一种方法是创建一个
itradingaprovider
,公开所需参数的列表。视图可以自动为这些参数创建一个输入表单,该表单与itradingaprovider
中的参数进行数据绑定。现在,当提供者请求一个ITradingApi
实例时,它可以利用这些参数创建具体实现的实例。显然,itradingaprovider
和ITradingApi
的实现是紧密耦合的,但我认为只要ITradingApi
的每个实现都带有相应的itradingaprovider
的实现,这就是您想要的吗
ninjectKernel.Get<MainViewModel>().WithConstructorArgument("tradingApi",
kernel.Get<ITaxCalculator>() .WithConstructorArgument("additionalParameter","someValue")));
ninjectKernel.Get(),
Get().WithConstructorArgument(“additionalParameter”、“someValue”);
试试类似的方法怎么样?创建名为IConnectStrategy
的新接口:
interface IConnectStrategy
{
void Connect();
}
将connectstrategy作为参数添加到ITradingApi
中的方法void CreateOrder(IConnectStrategy connectstrategy)
,并让每个供应商创建/指定自己的连接方法。例如,对于一个供应商,创建:
public class TCPConnectStrategy : IConnectStrategy
{
public TCPConnectStrategy(string hostName, int port)
{
/* ... */
}
public void Connect()
{
/* ... tcp connect ... */
}
}
(Connect可能不是最好的名称,甚至不是您实际正在做的事情,但请将其应用于任何适合您的项目的东西。)
评论后编辑:
创建一个策略,该策略只针对具有供应商特定参数的每个方法具有合同。然后将方法
void SetVendorStrategy(IVendorStrategy vendorStrategy)
(或属性)添加到ITradingAPI接口。策略的每个实现都有自己的构造函数和自己的参数,ITradingAPI接口的每个实现中的每个方法(需要特定于供应商的参数)都只需调用vendorStrategy.doSomethingWithvendorsspecificATA()
好的,我的两分钱,我不确定您知道什么。这只是为了帮助和尝试
我们让访问者访问您的api作为接口的构造:
public interface ITradingApi
{
Object CreateOrder();
IEnumerable<Object> GetAllSymbols();
}
public class TradingApi : ITradingApi
{
IvisitorAPI _VisitorAPI;
public TradingApi(IvisitorAPI visitorAPI)
{
_VisitorAPI = visitorAPI;
}
public Object CreateOrder()
{
var Order = new Object();
//bla bla bla
//here code relative to different visitor
_VisitorAPI.SaveOrder(Order);
return Order;
}
}
只有访问者才知道他需要什么来实现他对动作的理解。
因此,APi不需要额外的参数,我们将逻辑推到visitor类中。
只有当ewe知道谁是访问者时,才能创建这个访问者类,因此,在运行时肯定是这样
希望它能给你一些观点。我不知道整个理论是否适用于你的具体情况
不管怎样,我会尽力的;) 解决方案是使用我问题更新部分中概述的方法
itradingaprovider
扮演抽象工厂的角色,因此应重命名为ITradingApiFactory
。它将公开所需参数的列表,这些参数的值可以设置。视图可以使用此列表自动向用户提供输入表单,以便为每个参数输入值,因为只有用户知道参数的值。调用
Create
将使用以下参数:
public interface ITradingApiFactory
{
ITradingApi Create();
IEnumerable<Parameter> Parameters { get; }
}
public class Parameter
{
public Parameter(Type type, string name, string description)
{ Type = type; Name = name; Description = description; }
public Type Type { get; private set; }
public string Name { get; private set; }
public string Description { get; private set; }
public object Value { get; set; }
}
public class MT4TradingApiFactory : ITradingApiFactory
{
Dictionary<string, Parameter> _parameters;
public MT4TradingApiFactory()
{ /* init _parameters */ }
public ITradingApi Create()
{
return new MT4TradingApi(_parameters["hostname"].ToString(),
(int)_parameters["port"]);
}
IEnumerable<Parameter> Parameters { get { return _parameters.Values; } }
}
公共接口iTradingAPI工厂
{
ITradingApi Create();
IEnumerable参数{get;}
}
公共类参数
{
公共参数(类型、字符串名称、字符串描述)
{Type=Type;Name=Name;Description=Description;}
公共类型类型{get;private set;}
公共字符串名称{get;private set;}
公共字符串说明{get;private set;}
公共对象值{get;set;}
}
公共类MT4TradingApiFactory:ITradingApiFactory
{
字典参数;
公共MT4TradingApiFactory()
{/*init_参数*/}
公共ITradingApi创建()
{
返回新的MT4TradingApi(_参数[“主机名]).ToString(),
(int)_参数[“端口]);
}
IEnumerable参数{get{return\u Parameters.Values;}}
}
更多信息可在中找到
通过将参数作为属性提供给每个工厂实现,并更改
参数
类以使用表达式树直接处理这些属性,可以进一步改进此功能,使其更易于使用。如果有人对这种先进的工厂设计感兴趣,请留下评论。我认为您的供应商方法没有问题。你有两个顾虑:
ITradingAPI
,它为您可以执行的操作定义了一个契约public interface ITradingApiFactory
{
ITradingApi Create();
IEnumerable<Parameter> Parameters { get; }
}
public class Parameter
{
public Parameter(Type type, string name, string description)
{ Type = type; Name = name; Description = description; }
public Type Type { get; private set; }
public string Name { get; private set; }
public string Description { get; private set; }
public object Value { get; set; }
}
public class MT4TradingApiFactory : ITradingApiFactory
{
Dictionary<string, Parameter> _parameters;
public MT4TradingApiFactory()
{ /* init _parameters */ }
public ITradingApi Create()
{
return new MT4TradingApi(_parameters["hostname"].ToString(),
(int)_parameters["port"]);
}
IEnumerable<Parameter> Parameters { get { return _parameters.Values; } }
}
public interface ITradingApiTrader
{
ITradingApi Create(Type apiType);
}
public interface ITradingApiTrader
{
ITradingApi CreateMT4TradingApi();
ITradingApi CreateFooTradingApi();
ITradingApi CreateBarTradingApi();
// etc.
}
public interface ITradingApiTrader
{
ITradingApi Create<T>() where T : ITradingApi;
}