2011-03-01 39 views
6

Tôi là người mới bắt đầu đấu tranh với IoC và DI. Tôi muốn để có thể giải quyết các kết nối và kết nối nhà máy tự động bằng cách sử dụng autofac (hoặc bất kỳ công cụ thích hợp khác.IoC, nhà máy và đối số hàm tạo

Một kịch bản có thể được thay đổi việc thực hiện kết nối với nhau với các cơ sở hơn trong việc tìm, vv

Khi tôi áp dụng DI và IoC vào mã dưới đây, tôi nhận được một mớ hỗn độn của namedParameter trong nhà thầu vv Nhà máy kết nối trả về kết nối mới với một cổng duy nhất (ví dụ ngớ ngẩn, chỉ để cho thấy tôi cần giữ một số trạng thái trong nhà máy)

Tôi có thể sử dụng tính năng tiêm cho IP và cổng, nhưng theo cách đó, tôi sẽ không được đảm bảo rằng các kết nối sẽ có một IP hoặc cổng, đó là điểm của một nhà xây dựng. Ngoài ra, các tham số được đặt tên cũng làm cho tôi phụ thuộc vào tên của các đối số.

Ý tưởng, mẫu, con trỏ IoC được đánh giá cao!

Cập nhật:

cụ thể hơn: Làm thế nào tôi có thể thay đổi các lớp kết nối được tiêm? Tôi có nên dùng thuốc tiêm không? Hoặc bất kỳ thủ thuật tôi có thể làm được một giải quyết an toàn hơn với các đối số constructor?

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

Bây giờ, việc sử dụng:

//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()); 
+0

Có lẽ bạn có thể muốn làm rõ câu hỏi/vấn đề thực tế của mình với mã ở trên hoặc cho dù bạn chỉ sau liên kết tài liệu/mẫu cho một khung công tác IoC cụ thể. – Reddog

+0

Cảm ơn bạn đã bình luận, tôi đã cố gắng cụ thể hơn! – Larsbj

+0

Tôi sẽ đi trước với tiêm tài sản và đầu tiên giải quyết các obect và sau đó vượt qua các thuộc tính. – sajoshi

Trả lời

6

Một thay thế cho đi qua các đối số nhà xây dựng tại quyết thời gian là để mã hóa những tranh cãi trong hàm đăng ký:

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

Autofac sẽ sử dụng chức năng mà bất cứ khi nào nó cần để tạo ra các ví dụ nhà máy kết nối.

Vì chúng tôi đã định cấu hình ConnectionFactorySingleInstance, nó sẽ được chia sẻ giữa tất cả các thành phần phụ thuộc vào IConnectionFactory. Điều này có nghĩa ConnectionFactory nhu cầu để giữ trạng thái của nó giữa các cuộc gọi đến CreateConnection:

public class ConnectionFactory : IConnectionFactory 
{ 
    private int _fromPort; 

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

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

Nếu bạn có một một lần ConnectionFactory mà, nói, sử dụng một IP khác nhau, bạn có thể sử dụng một đăng ký tên:

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

Khi bạn muốn có một thành phần để sử dụng nhà máy đặc biệt thay vì một mặc định, bạn có thể sử dụng ResolveNamed method:

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

Đây là một kỹ thuật tiện dụng để định cấu hình một loại theo nhiều cách và sử dụng chúng ở những nơi cụ thể.

+0

Tôi không thể tin rằng tôi không nghĩ đến việc đăng ký một thể hiện thay vì lớp học, khái niệm này đơn giản và chỉ là những gì tôi cần. * tát trán * Cảm ơn bạn! – Larsbj

+0

nếu paramaters không liên tục thì sao? – sebas

+0

@sebas: Tôi thường tổ chức các loại đăng ký này thành các mô-đun. Các mô-đun chấp nhận các tham số cấu hình như URL và cổng trong các hàm tạo của chúng và sử dụng chúng trong các đăng ký. Xem câu trả lời này của tôi cho phương pháp cụ thể: http://stackoverflow.com/questions/3587380/dependency-injection-and-appsettings/3592370#3592370 –

2

Tôi không có kinh nghiệm với Autofac nhưng tôi giải quyết một vấn đề rất giống nhau trong Unity. Dưới đây là một đoạn:

Khi tôi cấu hình container của tôi tôi làm điều gì đó như thế này (điều này thậm chí có thể được thực hiện trong file config):

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

Sau đó, tôi có thể xây dựng các kết nối bằng cách chỉ nói:

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

hoặc chỉ định một tài sản phụ thuộc:

[Dependency] 
IConnection Connection {get;set;} 

hoặc như là một tham số tiêm cho công cụ xây dựng tiêm:

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

Tôi để cho IoC xử lý đảm bảo rằng không có hai chủ đề đang chia sẻ kết nối.

Mặc dù sự khác biệt với mẫu của bạn trong câu hỏi là tinh tế, nó loại bỏ các tham số từ mỗi lần khởi tạo cho phép bạn có nó như một thuộc tính phụ thuộc hoặc như một phần của một hàm tạo.

Hy vọng điều đó sẽ hữu ích.

+0

Cảm ơn câu trả lời của bạn, một ý tưởng tuyệt vời khác. Tôi đã không nghĩ về cách tiếp cận đó chút nào. – Larsbj

1

Cách tiếp cận linh hoạt có thể là tạo "AppConfigConnectionFactory" (hoặc WebConfig, DBConfig, v.v.) và bên ngoài các thuộc tính này thông qua cấu hình. Tôi chưa bao giờ cảm thấy phải tải dữ liệu cấu hình trực tiếp từ khung DI.

+0

Ý tưởng tuyệt vời, cảm ơn! – Larsbj

Các vấn đề liên quan