7

Tôi đang sử dụng hộp chứa Autofac IoC với phần bổ trợ MVC4, cung cấp phạm vi đời sống InstancePerHttpRequest. Tuy nhiên trong dự án của tôi, tôi có các chủ đề web, api và nền công nhân. Trong ví dụ sau tôi giả định phạm vi InstancePerHttpRequest không có nghĩa là nhiều khi không có nguồn gốc từ một yêu cầu web.Có thể xác định nhiều phạm vi thời gian của Autofac trên đăng ký không?

builder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>() 
    .InstancePerHttpRequest() 

Tôi tự hỏi liệu có thể làm điều gì đó giống như ví dụ sau và có vùng chứa chọn phạm vi thời gian phù hợp nhất không?

builder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>() 
    .InstancePerHttpRequest() 
    .InstancePerApiRequest() 
    .InstancePerDependency(); 

Trong trường hợp này những gì tôi có ý định xảy ra là nếu yêu cầu xuất phát từ một yêu cầu web sau đó nó sẽ chọn phạm vi InstancePerHttpRequest, nếu nó xuất phát từ một yêu cầu WebAPI nó sẽ chọn phạm vi InstancePerApiRequest và nếu nó được sử dụng bởi các luồng công nhân ứng dụng, nó sẽ sử dụng phạm vi InstancePerDependency?

Bất kỳ ý tưởng nào nếu điều này hoặc điều gì đó tương tự đều có thể xảy ra?
Cảm ơn

Trả lời

10

Câu hỏi này có một số chồng chéo khá nặng với những:

Bạn sẽ muốn kiểm tra những người ra cho một số ý tưởng.

Câu trả lời ngắn gọn là: Loại điều này không được hỗ trợ ngoài hộp. Bạn sẽ cần thực hiện một trong hai điều.

Tùy chọn: Bạn có thể có một vùng chứa khác cho chủ đề nền. Điều này sẽ không cho phép bạn chia sẻ các ứng dụng đơn cấp, nhưng điều đó có thể được chấp nhận cho ứng dụng của bạn.

Tùy chọn: Bạn có thể tạo hai phạm vi tồn tại ngoài vùng chứa và thực hiện các đăng ký khác nhau như một phần của cuộc gọi đến BeginLifetimeScope. Điều này sẽ cho phép bạn chia sẻ các ứng dụng đơn cấp và có phạm vi thời gian sống khác nhau cho cùng các thành phần trong các ngữ cảnh khác nhau. Tuy nhiên, việc quản lý đăng ký khó hơn một chút và bạn sẽ cần hai trình định vị dịch vụ khác nhau (ví dụ: DependencyResolver) vì mỗi ngữ cảnh hợp lý sẽ cần phải giải quyết từ phạm vi của riêng nó.

var builder = new ContainerBuilder(); 
builder.RegisterType<AppLevelSingleton>().SingleInstance(); 
var container = builder.Build(); 

// Create a nested lifetime scope for your background threads 
// that registers things as InstancePerDependency, etc. Pass 
// that scope to whatever handles dependency resolution on the thread. 
var backgroundScope = container.BeginLifetimeScope(
    b => b.RegisterType<DatabaseFactory>() 
     .As<IDatabaseFactory>() 
     .InstancePerDependency()); 

// Create a nested lifetime scope for the web app that registers 
// things as InstancePerHttpRequest, etc. Pass that scope 
// as the basis for the MVC dependency resolver. 
var webScope = container.BeginLifetimeScope(
    b => b.RegisterType<DatabaseFactory>() 
     .As<IDatabaseFactory>() 
     .InstancePerHttpRequest()); 
var resolver = new AutofacDependencyResolver(webScope); 
DependencyResolver.SetResolver(resolver); 

Nếu bạn thực sự muốn nhận được ưa thích với tùy chọn này, bạn có thể thực hiện một phong tục IContainer có thể phát hiện mà bối cảnh nó ở và giải quyết mọi thứ từ phạm vi lồng nhau thích hợp. Đây là cách hỗ trợ Autofac đa nhiệm hoạt động. Tuy nhiên, đó là một giải pháp có liên quan nhiều hơn nên tôi sẽ không viết ra tất cả ở đây. Kiểm tra nguồn Autofac cho hỗ trợ đa nhiệm cho các ví dụ.

Tùy chọn: Bạn có thể sử dụng một "mẫu số chung nhỏ nhất" loại đăng ký như InstancePerDependency hoặc InstancePerLifetimeScope và bỏ qua khái niệm của việc có một đời khác nhau cho các bộ phận khác nhau của ứng dụng.

Lưu ý rằng, ngay bây giờ, về mặt kỹ thuật, nội bộ, không có sự khác biệt giữa những gì InstancePerHttpRequestInstancePerWebApiRequest làm. Cả hai đều sôi xuống chính xác cùng một điều và có hiệu quả hoán đổi cho nhau. (Tôi không thể hứa nó sẽ luôn luôn như vậy mãi mãi, nhưng tôi không biết tại sao nó sẽ cần phải thay đổi.)

+0

Tuyệt vời! Cảm ơn bạn đã trả lời kỹ lưỡng, điều này giúp ích rất nhiều. – chriskopec

+0

nghĩ rằng điều này sẽ hữu ích. một ví dụ là sử dụng khung công tác EF kể từ hành động api trên web dbcontext, nếu nó gọi lớp cần truy cập vào cơ sở dữ liệu bằng một chuỗi mới, rất có thể là nếu nó chỉ là instanceperhttprequest, nó sẽ ném ngoại lệ, vì vậy cần có sự linh hoạt để có InstancePerLifetimeScope. nó gần như tốt hơn để có InstancePerLifetimeScope. – koo9

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