2016-07-20 24 views
5

Tôi muốn sử dụng AutoFac để tiêm hiệu trưởng hiện tại vào các đối tượng cần nó. Giả sử tôi có một đối tượng (AuthorizationValidator) đang thực hiện kiểm tra bảo mật. Nó trông giống như sau:AutoFac: Tiêm các giá trị NULL

public AuthorizationValidator : IAuthorizationValidator 
{ 
    public AuthorizationValidator(IDataAccess dataAccess, IPrincipal principal) 
    { 
    // Save injected objects 
    ... 
    } 

    public bool CheckPermission(Guid objectId, Action action) 
    { 
    // Check if we are authorized at all 
    if (this.principal == null) 
     return false; 

    // Check the permission in the database 
    ... 
    } 
} 

Đối với ứng dụng web của tôi AuthorizationValidator được đăng ký và tôi sử dụng đăng ký sau đây để tiêm chính:

builder.Register<IPrincipal>((c, p) => HttpContext.Current?.User); 

loại khác của các ứng dụng sử dụng chính hay cái gì tương tự của chủ đề . Tất cả các đối tượng yêu cầu hiệu trưởng phải được tiêm chính hiệu trưởng.

Nếu một cuộc gọi được thực hiện mà không được phép, sau đó AutoFac đặt ra một ngoại lệ cho tôi biết rằng nó không thể cung cấp đối tượng IPrincipal, bởi vì nhà máy trả về null. Trong trường hợp này, một hiệu trưởng trống là tốt và không nên đưa ra một ngoại lệ.

+0

Tôi không biết nội dung bên trong Autofac là gì, nhưng có khả năng điều này có thể hoạt động: 'builder.Register ((c, p) => (IPrincipal) HttpContext.Current? .User);' –

+0

Nói chung nói, các khung công tác IoC sẽ không cho phép bạn tiêm null một cách có chủ ý. Đó không chỉ là một điều Autofac. –

+0

[Mô hình đối tượng Null] (https://en.wikipedia.org/wiki/Null_Object_pattern) có phải là giải pháp thay thế như tôi đã đề xuất trong câu trả lời của tôi không? – fknx

Trả lời

5

Trong Autofac documentation, họ khuyên bạn nên sử dụng Null Object pattern cho các trường hợp như vậy. Bạn có thể tạo một lớp NullPrincipal kế thừa từ giao diện IPrincipal với một hàm tạo riêng tư chỉ hiển thị trường readonlystatic cung cấp trường hợp mặc định. Sau đó, bạn có thể trở lại trường hợp này thay vì null:

builder.Register<IPrincipal>((c, p) => HttpContext.Current?.User ?? NullPrincipal.Default); 

Tất nhiên bạn sẽ phải cập nhật tất cả các nơi trong mã của bạn, nơi bạn đang kiểm tra nếu hiệu trưởng là null và kiểm tra xem nó là bằng với NullPrincipal.Default để thay thế.

1

Để giải quyết vấn đề này, tôi đã tạo ra các giao diện IPrincipalFactory rằng có thể có được hiệu trưởng hiện tại mà không đi qua AutoFac:

public AuthorizationValidator : IAuthorizationValidator 
{ 
    public AuthorizationValidator(IDataAccess dataAccess, IPrincipalFactory principalFactory) 
    { 
    // Save injected objects 
    _dataAccess = dataAccess; 
    _principal = principalFactory.GetCurrentPrincipal(); 
    } 

    public bool CheckPermission(Guid objectId, Action action) 
    { 
    // Same as previous example 
    ... 
    } 
} 

public interface IPrincipalFactory 
{ 
    IPrincipal GetCurrentPrincipal(); 
} 

Đối với các ứng dụng ASP.NET tôi sẽ đăng ký các đối tượng sau đây là IPrincipalFactory:

public class IAspNetPrincipalFactory : IPrincipalFactory 
{ 
    public IPrincipal GetCurrentPrincipal() => HttpContext.Current?.User; 
} 

Mặc dù công trình này, tôi không hoàn toàn hài lòng với giải pháp này.

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