簡體   English   中英

IoC,工廠和構造函數參數

[英]IoC, factories and constructor arguments

我是IoC和DI的初學者。 我希望能夠使用autofac(或任何其他合適的.NET IoC工具)動態解析連接和連接工廠。

一個場景可能是將連接實現更改為另一個具有更多跟蹤設施的實現。

當我將DI和IoC應用於下面的代碼時,我在構造函數等中得到了一堆namedParameter。連接工廠返回一個帶有唯一端口的新連接(愚蠢的例子,只是為了表明我需要在工廠中保持某種狀態)

我想我可以使用屬性注入的IP和端口范圍,但是這樣,我不能保證連接將具有IP或端口,這是構造函數的要點。 此外,命名參數也使我依賴於參數的名稱。

想法,模式,IoC指針非常感謝!

更新:

更具體:如何將連接類更改為可注入? 我應該選擇房產嗎? 或者我能做的任何技巧都可以通過構造函數參數獲得更加類型安全的解析?

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());

在resolve-time傳遞構造函數參數的另一種方法是在注冊函數中對這些參數進行編碼:

builder
.Register(c => new ConnectionFactory("127.0.0.1", 80))
.As<IConnectionFactory>()
.SingleInstance();

只要需要創建連接工廠實例,Autofac就會使用該功能。

由於我們將ConnectionFactory配置為SingleInstance ,因此它將在依賴於IConnectionFactory所有組件之間共享。 這意味着ConnectionFactory需要在CreateConnection調用之間保持自己的狀態:

public class ConnectionFactory : IConnectionFactory
{
    private int _fromPort;

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

    public IConnection CreateConnection()
    {
        return new Connection(ip, _fromPort++);
    }
}

如果您有一個一次性的ConnectionFactory ,比如使用不同的IP,您可以使用命名注冊:

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

如果希望組件使用該特定工廠而不是默認工廠,則可以使用ResolveNamed方法

builder.Register(c => new Foo(c.ResolvedNamed<IConnectionFactory>("AlernateConnectionFactory")));

這是一種以多種方式配置類型並在特定位置使用它的方便技術。

我對Autofac沒有經驗,但我在Unity中解決了一個非常類似的問題。 這是一個片段:

當我配置我的容器時,我做了類似的事情(這甚至可以在配置文件中完成):

string connectionString = ConfigurationManager.ConnectionStrings["XYZ"].ConnectionString;
Container.RegisterType<IConnection, Connection>(new PerThreadLifetimeManager(), 
                                                new InjectionConstructor(connectionString));

稍后,我可以通過以下方式建立連接:

IConnection myConnection = Container.Resolve<IConnection>();

或指定依賴屬性:

[Dependency]
IConnection Connection {get;set;}

或作為構造函數注入的可注入參數:

[InjectionConstructor]
public SomeClassThatUsesConnections(IConnection connection)
{ ... }

我離開PerThreadLifetimeManager指出我讓IoC處理確保沒有兩個線程共享連接。

雖然問題中樣本的差異很小,但它確實從每個實例化中刪除了參數,這些參數允許您將其作為依賴項屬性或作為注入構造函數的一部分。

希望有所幫助。

靈活的方法可能是創建“AppConfigConnectionFactory”(或WebConfig,DBConfig等...)並通過配置外部化這些屬性。 我從來沒有感覺到直接從DI框架加載配置數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM