Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.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#_.net_Architecture_Dependency Injection - Fatal编程技术网

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;
    }