C# IoC、工厂和构造函数参数

C# IoC、工厂和构造函数参数,c#,.net,inversion-of-control,autofac,C#,.net,Inversion Of Control,Autofac,我是一个与IoC和DI斗争的初学者。我希望能够使用autofac(或任何其他合适的.NET IoC工具)动态解析连接和连接工厂 一个场景可能是将连接实现更改为另一个具有更多跟踪功能等的连接实现 当我将DI和IoC应用于下面的代码时,我在构造函数等中得到了一堆namedParameter。连接工厂返回一个具有唯一端口的新连接(愚蠢的示例,只是为了说明我需要在工厂中保持某种状态) 我想我可以对IP和端口范围使用属性注入,但是那样的话,我不能保证连接会有IP或端口,这是构造函数的要点。 此外,命名参数

我是一个与IoC和DI斗争的初学者。我希望能够使用autofac(或任何其他合适的.NET IoC工具)动态解析连接和连接工厂

一个场景可能是将连接实现更改为另一个具有更多跟踪功能等的连接实现

当我将DI和IoC应用于下面的代码时,我在构造函数等中得到了一堆namedParameter。连接工厂返回一个具有唯一端口的新连接(愚蠢的示例,只是为了说明我需要在工厂中保持某种状态)

我想我可以对IP和端口范围使用属性注入,但是那样的话,我不能保证连接会有IP或端口,这是构造函数的要点。 此外,命名参数也使我依赖于参数的名称

非常感谢您的想法、模式和国际奥委会的指导

更新:

更具体地说:如何将连接类更改为可注入的?我应该进行财产注入吗?或者我能做些什么,用构造函数参数获得更安全的类型解析

public interface IConnection {
     void Open();
     void Close();
     string Execute(string command);
}

public interface IConnectionFactory {
     IConnection CreateConnection();
}

public class Connection : IConnection {
   ...
   public Connection(String ip, int port) {
     _ip = ip;
     _port = port;
   }

   public string Execute() {}   
   public void Open() {}
   public void Close() {}
}


public class ConnectionFactory : IConnectionFactory {
    //How would I resolve this?
    public ConnectionFactory(string ip, int fromPort) {
        ...
    }
    public IConnection CreateConnection()  {
        //How would I resolve this? 
        return new Connection(ip, fromPort++);
    }
}
现在,用法如下:

//Register
builder.RegisterType<Connection>().As<IConnection>();
builder.RegisterType<ConnectionFactory>().As<IConnectionFactory>().SingleInstance();
...

var connection = container.Resolve<IConnectionFactory>(
      new NamedParameter("ip", "127.0.0.1"), 
      new NamedParameter("fromPort", 80).CreateConnection());
//寄存器
builder.RegisterType().As();
builder.RegisterType().As().SingleInstance();
...
var connection=container.Resolve(
新命名参数(“ip”、“127.0.0.1”),
新名称参数(“fromPort”,80).CreateConnection());

我对Autofac没有经验,但我在Unity中解决了一个非常类似的问题。下面是一个片段:

配置容器时,我会执行以下操作(甚至可以在配置文件中执行此操作):

或作为构造函数注入的可注入参数:

[InjectionConstructor]
public SomeClassThatUsesConnections(IConnection connection)
{ ... }
我离开PerThreadLifetimeManager是为了指出,我让IoC负责确保没有两个线程共享一个连接

尽管在这个问题上与您的示例的区别是细微的,但它确实从每个实例化中删除了参数,从而允许您将其作为依赖项属性或注入构造函数的一部分


希望有帮助

一种灵活的方法可能是创建“AppConfigConnectionFactory”(或WebConfig、DBConfig等),并通过配置将这些属性外部化。我从来没有觉得直接从DI框架加载配置数据是正确的

在解析时传递构造函数参数的另一种方法是在注册函数中对这些参数进行编码:

builder
.Register(c => new ConnectionFactory("127.0.0.1", 80))
.As<IConnectionFactory>()
.SingleInstance();
如果您有一个一次性的
连接工厂
,它使用不同的IP,您可以使用命名注册:

builder
.Register(c => new ConnectionFactory("192.168.0.1", 80))
.Named<IConnectionFactory>("AlernateConnectionFactory")
.SingleInstance();

这是一种以多种方式配置类型并在特定位置使用它们的简便技术。

也许您想澄清您对上述代码的实际问题/问题,或者您是否只是在查看特定IoC框架的文档链接/示例。谢谢您的评论,我已经尝试过更具体一些!我会继续进行属性注入,首先解决OBCT,然后传递属性。谢谢你的回答,这是另一个好主意。我根本没有考虑这种方法,我不敢相信我没有考虑注册一个实例而不是类,这个概念很简单,正是我需要的。拍拍额头谢谢!如果参数不是常数怎么办?@sebas:我通常将这些类型的注册组织成模块。模块在其构造函数中接受URL和端口等配置参数,并在注册中使用它们。具体方法见我的回答:
[InjectionConstructor]
public SomeClassThatUsesConnections(IConnection connection)
{ ... }
builder
.Register(c => new ConnectionFactory("127.0.0.1", 80))
.As<IConnectionFactory>()
.SingleInstance();
public class ConnectionFactory : IConnectionFactory
{
    private int _fromPort;

    public ConnectionFactory(string ip, int fromPort)
    {
        ...
        _fromPort = fromPort;
    }

    public IConnection CreateConnection()
    {
        return new Connection(ip, _fromPort++);
    }
}
builder
.Register(c => new ConnectionFactory("192.168.0.1", 80))
.Named<IConnectionFactory>("AlernateConnectionFactory")
.SingleInstance();
builder.Register(c => new Foo(c.ResolvedNamed<IConnectionFactory>("AlernateConnectionFactory")));