2014-12-04 16 views
9

Chúng tôi đang cố gắng sử dụng Ninject trong một đường ống Owin với WebAPI. Chúng tôi có mọi thứ được thiết lập theo số this documentation, nhưng chúng tôi không thể nhận được InRequestScope() để hoạt động.Sử dụng Ninject với Owin và InRequestScope

Đây là một phần quan trọng của startup.cs

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     HttpConfiguration config = new HttpConfiguration(); 

     // Web API routes 
     config.MapHttpAttributeRoutes(); 

     // Ninject Setup 
     app.UseNinjectMiddleware(NinjectConfig.CreateKernel); 
     app.UseNinjectWebApi(config); 
    } 

}

NinjectConfig trông giống như sau:

public sealed class NinjectConfig 
{ 
    public static IKernel CreateKernel() 
    { 
     var kernel = new StandardKernel(); 

     INinjectModule[] modules = 
     { 
      new ApplicationModule() 
     };  

     instance.Load(modules); 

     // Do we still need to do this wtih Owin? 
     instance.Bind<IHttpModule>().To<OnePerRequestHttpModule>(); 
    } 
} 

ApplicationModule chúng tôi sống trong một dự án cơ sở hạ tầng riêng biệt với quyền truy cập vào tất cả các lớp khác nhau của chúng tôi, để xử lý DI & Lập bản đồ:

public class ApplicationModule: NinjectModule 
{ 

    public override void Load() 
    { 
     // IUnitOfWork/EF Setups 
     Bind<ApplicationContext>().ToSelf().InRequestScope(); 

     Bind<IUnitOfWork>().ToMethod(ctx => ctx.Kernel.Get<ApplicationContext>()}); 

     Bind<ApplicationContext>().ToMethod(ctx => ctx.Kernel.Get<ChromLimsContext>()}).WhenInjectedInto<IDal>(); 

     // other bindings for dals and business objects, etc. 
    } 
} 

Sau đó, chúng tôi có một vài giao diện:

public interface IUnitOfWork() 
{ 
    void SaveChanges(); 

    Task SaveChangesAsync(); 
} 

public interface IDal() 
{ 
    // Crud operations, Sync and Async 
} 

sau đó các lớp học thực tế của chúng tôi sử dụng những:

public class SomeBusinessObject 
{ 
    private IUnitOfWork _uow; 
    private IDal _someDal; 

    public SomeBusinessObject(IUnitOfWork uow, IDal someDal) 
    { 
     _uow = uow; 
     _someDal = someDal; 
    } 

    public Task<SomeResult> SaveSomething(Something something) 
    { 
     _someDal.Save(something); 
     _uow.SaveChanges(); 
    } 
} 

Một số Dal

public class SomeDal : IDal { 

    private ApplicationContext _applicationContext; 

    public SomeDal(ApplicationContext applicationContext) 
    { 
     _applicationContext = applicationContext; 
    } 

    public void Save(Something something) 
    { 
     _applicationContext.Somethings.Add(something); 
    } 
} 

EF chúng tôi DbContext

public class ApplicationContext : DbContext, IUnitOfWork 
{ 
    // EF DBSet Definitions 

    public void SaveChanges() 
    { 
     base.SaveChanges(); 
    } 

} 

Hi vọng là cho mọi yêu cầu, một trường hợp duy nhất của ApplicationContext được tạo ra và tiêm vào các đối tượng kinh doanh như một thực hiện IUnitOfWork và vào IDals như một ApplicationContext.

Thay vào đó điều đang xảy ra là một phiên bản mới của ApplicationContext đang được tạo cho mỗi lớp đơn lẻ sử dụng nó. Nếu tôi chuyển đổi phạm vi từ InRequestScope thành InSingletonScope, thì (như mong đợi) chính xác 1 cá thể được tạo cho toàn bộ ứng dụng và được tiêm đúng vào các lớp được chỉ định. Kể từ đó hoạt động, tôi giả định đây không phải là một vấn đề ràng buộc, nhưng thay vì một vấn đề với phần mở rộng InRequestScope.

Vấn đề duy nhất tôi có thể tìm thấy tương tự với những gì tôi đang gặp phải là this one, nhưng tiếc là giải pháp không hoạt động. Tôi đã tham khảo tất cả các gói mà anh ta đã chỉ định trong cả dự án WebApi và Infrastructure, và tôi đã kiểm tra lại để chắc chắn rằng chúng đang được sao chép vào thư mục build.

Tôi đang làm gì sai?

Chỉnh sửa: Một số thông tin bổ sung. Nhìn vào mã nguồn Ninject trong cả hai Ninject.Web.WebApi.OwinHost và Ninject.Web.Common.OwinHost, có vẻ như Owin Middleware thêm OwinWebApiRequestScopeProvider làm IWebApiRequestScopeProvider. Nhà cung cấp này sau đó được sử dụng trong phương thức mở rộng InRequestScope() để trả về một phạm vi được đặt tên có tên là "Ninject_WebApiScope". Điều này sẽ có mặt cho đến khi lớp đích được tiêm vào công tắc. Phạm vi được đặt tên sau đó biến mất và phạm vi mới được tạo. Tôi nghĩ rằng đây có thể là những gì @BatteryBackupUnit đang đề cập đến trong nhận xét của họ, nhưng tôi không biết cách sửa nó.

+1

tôi đoán sẽ là thứ hai 'Bind của bạn () 'gây ra điều này. Bạn không đặt nó thành 'InRequestScope()' – LukeP

+0

Thật không may là nó không hoạt động. Tôi cũng đã cố gắng chỉ ràng buộc các ApplicationContext cho chính nó InRequestScope, và sau đó chỉ ràng buộc IUnitOfWork ToMethod (ctx => ctx.Kernel.Get ()). InRequestScope() – aasukisuki

+1

Liệu '.InRequestScope() 'làm việc cho bất kỳ * * ràng buộc? Có một vấn đề "được biết" liên quan đến việc cài đặt/nâng cấp gói nuget ninject, nơi nó không được thiết lập đúng và công cụ ninject cụ thể-phạm vi yêu cầu không được đăng ký chính xác. '.InRequestScope()' không có tác dụng - đáng buồn là thậm chí không ném một ngoại lệ. – BatteryBackupUnit

Trả lời

4

Chủ đề này liên quan đến vấn đề này ...

https://github.com/ninject/Ninject.Web.WebApi/issues/17

Tôi đã phát hiện ra rằng hành vi của InRequestScope dường như thay đổi tùy thuộc vào cách bạn tiêm chúng. Ví dụ:

public ValuesController(IValuesProvider valuesProvider1, IValuesProvider valuesProvider2) 
{ 
    this.valuesProvider1 = valuesProvider1; 
    this.valuesProvider2 = valuesProvider2; 
} 

Ninject sẽ tạo và tiêm cùng một thể hiện của IValuesProvider. Tuy nhiên, nếu phương pháp được viết là ...

/// <summary> 
/// Initializes a new instance of the <see cref="ValuesController"/> class. 
/// </summary> 
/// <param name="valuesProvider">The values provider.</param> 
public Values2Controller(IKernel kernel) 
{ 
    this.valuesProvider1 = kernel.Get<IValuesProvider>(); 
    this.valuesProvider2 = kernel.Get<IValuesProvider>(); 
} 

... điều này sẽ tạo hai trường hợp mới.

+0

Chúng tôi đã kết thúc chuyển sang SimpleInjector, nhưng câu trả lời này là tốt nhất, chỉ ra rằng đây là một lỗi được biết đến trong Ninject – aasukisuki

3

Dựa trên thông tin trong liên kết trong bài viết @ Mick của tôi đã kết thúc thêm phương pháp khuyến nông của riêng tôi như thế này. Tôi không chắc chắn về những nhược điểm.

public static class CustomRequestScope 
{ 
    public static Ninject.Syntax.IBindingNamedWithOrOnSyntax<T> InCustomRequestScope<T>(this Ninject.Syntax.IBindingInSyntax<T> syntax) 
    { 
     return syntax.InScope(ctx => HttpContext.Current.Handler == null ? null : HttpContext.Current.Request); 
    } 
} 

Tôi xem xét chuyển sang vùng chứa khác vì sự cố này.

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