【问题标题】:AutoFac: Inject NULL valuesAutoFac:注入 NULL 值
【发布时间】:2016-07-20 09:01:08
【问题描述】:

我想使用 AutoFac 将当前主体注入需要它的对象中。假设我有一个正在执行安全检查的对象 (AuthorizationValidator)。它看起来像这样:

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
     ...
  }
}

对于我的 Web 应用程序,AuthorizationValidator 已注册,我使用以下注册来注入主体:

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

其他类型的应用程序使用线程的主体或类似的东西。所有需要主体的对象都会注入正确的主体。

如果在未经授权的情况下进行调用,则 AutoFac 会引发异常,告诉我它无法提供 IPrincipal 对象,因为工厂返回了 null。在这种情况下,空主体是可以的,不应引发异常。

【问题讨论】:

  • 我不知道 Autofac 里面有什么,但它有可能会起作用:builder.Register&lt;IPrincipal&gt;((c, p) =&gt; (IPrincipal)HttpContext.Current?.User);
  • 一般来说,IoC 框架不会让你故意注入 null。这不仅仅是 Autofac 的事情。
  • Null Object pattern 会像我在回答中建议的那样替代吗?
  • 虽然我最终使用了如果没有主体则返回 null 的主体提供程序,但我认为在大多数情况下 Null 对象模式可能会更好,因此我将其标记为最佳答案.

标签: c# null autofac


【解决方案1】:

在 Autofac documentation 中,他们建议在此类情况下使用 Null Object pattern。您可以创建一个从IPrincipal 接口继承的NullPrincipal 类,该类具有一个仅公开提供默认实例的readonly static 字段的私有构造函数。然后你可以返回这个实例而不是 null:

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

当然,您必须更新代码中检查主体是否为空的所有位置,并检查它是否等于 NullPrincipal.Default

【讨论】:

    【解决方案2】:

    为了解决这个问题,我创建了IPrincipalFactory接口,可以不经过AutoFac获取当前principal:

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

    对于 ASP.NET 应用程序,我会将以下对象注册为 IPrincipalFactory:

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

    虽然这可行,但我对这个解决方案并不完全满意。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-21
      相关资源
      最近更新 更多