2012-06-02 46 views
9

Vấn đề (trừu tượng)Autofac - Lifetime và các module

Cho một mô-đun mà đăng ký phụ thuộc X. phụ thuộc X có một đời khác nhau trong một ứng dụng MVC3 (lâu dài trên mỗi HttpRequest) sau đó trong một ứng dụng giao diện điều khiển (phụ thuộc mỗi lifetimescope với một tên). Ở đâu hoặc làm thế nào để xác định tuổi thọ của phụ thuộc X?

Trường hợp

Tôi đã đặt tất cả các cơ sở dữ liệu của tôi liên quan đến mã trong một hội đồng với một mô-đun trong đó mà đăng ký tất cả các kho. Bây giờ đăng ký ISession (Nhibernate) cũng nằm trong module.

ISession là phụ thuộc X (trong trường hợp sự cố đã cho). ISession có tuổi thọ khác nhau trong một ứng dụng MVC3 (suốt đời cho mỗi yêu cầu) sau đó trong một ứng dụng giao diện điều khiển, nơi tôi xác định một vòng đời có tên.

Nếu đăng ký ISession nằm ngoài mô-đun? Sẽ là lạ vì nó là một chi tiết thực hiện.

Trường hợp tốt nhất để làm ở đây là gì? Thiết kế lỗ hổng hoặc có công trình thông minh cho điều này :)?

+0

Bạn có lưu ý đến các kết nối cụ thể trong cuộc đời không? Nếu vậy, chúng có khác nhau trong suốt thời gian tồn tại cho mỗi ứng dụng hay không? Điều gì về tổng hợp? Bạn có bơi trong một số ứng dụng chứ không phải trong ứng dụng khác không? –

+0

Nó giống như bạn nói "Các phần mở rộng MVC sử dụng một phạm vi được đặt tên để đạt được cơ chế một lần cho mỗi yêu cầu." Http được đặt tên là phạm vi không có khi bạn sử dụng các mô-đun trong giao diện điều khiển ứng dụng. Hiện tại tôi đang xem xét đơn vị công việc sẽ là gì và sẽ được đóng gói trong phạm vi nào. –

Trả lời

7

Với mô tả trường hợp sử dụng của bạn, tôi muốn nói bạn có một vài tùy chọn.

Đầu tiên, bạn chỉ có thể yêu cầu mỗi ứng dụng đăng ký bộ phụ thuộc riêng của họ bao gồm phạm vi toàn thời gian. Có một hoặc hai "bản sao" đoạn mã trong khía cạnh này không phải là lớn của một thỏa thuận xem xét sự khác biệt giữa các ứng dụng và thực tế là đăng ký xuất hiện khá nhỏ.

Thứ hai, bạn có thể bọc phần chung (trừ phạm vi tuổi thọ) thành phương pháp mở rộng ContainerBuilder có thể được sử dụng trong mỗi ứng dụng. Nó sẽ vẫn có nghĩa là mỗi ứng dụng có một chút "mã trùng lặp" nhưng logic chung sẽ được bao bọc trong một phần mở rộng đơn giản.

public static IRegistrationBuilder<TLimit, ScanningActivatorData, DynamicRegistrationStyle> 
    RegisterConnection<TLimit, ScanningActivatorData, DynamicRegistrationStyle>(this ContainerBuilder builder) 
{ 
    // Put the common logic here: 
    builder.Register(...).AsImplementedInterfaces(); 
} 

tiêu thụ như một phần mở rộng trong mỗi ứng dụng sẽ như thế nào:

builder.RegisterConnection().InstancePerHttpRequest(); 
// or 
builder.RegisterConnection().InstancePerLifetimeScope(); 

Cuối cùng, nếu bạn biết nó là một trong hai web hoặc phi web, bạn có thể làm một module tùy chỉnh để xử lý chuyển đổi :

public class ConnectionModule : Autofac.Module 
{ 
    bool _isWeb; 
    public ConnectionModule(bool isWeb) 
    { 
    this._isWeb = isWeb; 
    } 

    protected override void Load(ContainerBuilder builder) 
    { 
    var reg = builder.Register(...).AsImplementedInterfaces(); 
    if(this._isWeb) 
    { 
     reg.InstancePerHttpRequest(); 
    } 
    else 
    { 
     reg.InstancePerLifetimeScope(); 
    } 
    } 
} 

Trong mỗi ứng dụng, sau đó bạn có thể đăng ký các module:

// Web application: 
builder.RegisterModule(new ConnectionModule(true)); 

// Non-web application: 
builder.RegisterModule(new ConnectionModule(false)); 

Ngoài ra, bạn đã đề cập phạm vi cuộc đời của bạn trong các ứng dụng khác có tên.Bạn có thể làm cho mô-đun của bạn lấy tên:

public class ConnectionModule : Autofac.Module 
{ 
    object _scopeTag; 
    public ConnectionModule(object scopeTag) 
    { 
    this._scopeTag = scopeTag; 
    } 

    protected override void Load(ContainerBuilder builder) 
    { 
    var reg = builder.Register(...) 
        .AsImplementedInterfaces() 
        .InstancePerMatchingLifetimeScope(this._scopeTag); 
    } 
} 

tiêu thụ cũng tương tự như:

// Web application (using the standard tag normally provided): 
builder.RegisterModule(new ConnectionModule("httpRequest")); 

// Non-web application (using your custom scope name): 
builder.RegisterModule(new ConnectionModule("yourOtherScopeName")); 

tôi muốn giới thiệu với chỉ đơn giản là sử dụng InstancePerLifetimeScope trong một ứng dụng web trừ khi đó là thực sự những gì bạn dự định. Như đã nêu trong các câu trả lời/nhận xét khác, InstancePerHttpRequest sử dụng phạm vi cuộc đời được đặt tên cụ thể để đảm bảo an toàn để tạo phạm vi cuộc sống của trẻ em; sử dụng InstancePerLifetimeScope không có giới hạn như vậy để bạn sẽ thực sự nhận được một kết nối cho mỗi phạm vi con chứ không phải một kết nối cho yêu cầu. Cá nhân tôi, không cho rằng các nhà phát triển khác sẽ không sử dụng phạm vi cuộc sống của trẻ em (which is a recommended practice), vì vậy trong các ứng dụng của tôi, tôi rất cụ thể. Nếu bạn có toàn quyền kiểm soát ứng dụng của mình và bạn có thể đảm bảo rằng bạn không tạo thêm phạm vi con hoặc bạn thực sự muốn một kết nối cho mỗi phạm vi, thì có thể InstancePerLifetimeScope sẽ giải quyết vấn đề của bạn.

+0

Cảm ơn câu trả lời mở rộng! Tôi đã đưa ra điều này: https://gist.github.com/2883596 Bạn gọi ConfigureUnitOfWork để cấu hình trên IUnitOfWork phụ thuộc mà ẩn các chi tiết thực hiện. Ngoài ra giải pháp này không phụ thuộc vào phần mở rộng MVC3. Chỉ có nhược điểm để giải pháp này là bạn có thể cấu hình tất cả mọi thứ trong khi bạn chỉ muốn cho phép suốt đời ,, có thể được abstracted đi, nhưng không cắt nếu bây giờ :) –

0

Thực tiễn phổ biến là sử dụng một kết nối cho mỗi yêu cầu http. Trong trường hợp đó, các kết nối sẽ được đăng ký sử dụng .InstansePerLifetimeScope(). Ví dụ: bạn có thể làm điều gì đó như:

builder 
    .Register(c => { 
         var conn = new SqlConnection(GetConnectionString()); 
         conn.Open(); 
         return conn; 
        }) 
    .AsImplementedInterfaces() 
    .InstancePerLifetimeScope(); 
+0

Có, tôi biết bạn có thể làm điều đó. Vấn đề của tôi là nơi để làm điều này? Đó là điều mà module 'dữ liệu' phải chịu trách nhiệm. Tuy nhiên có vẻ như không có cách nào để đăng ký kết nối bên trong module và thiết lập tuổi thọ bên ngoài module. –

+0

Tôi sẽ đăng ký kết nối và đặt thời gian tồn tại bên trong mô-đun dữ liệu. –

+0

Thats vấn đề trong một ứng dụng MVC đời là khác nhau như trong một ứng dụng giao diện điều khiển, nơi không có những điều như một bối cảnh như Http –

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