【问题标题】:Using Autofac's resolver on demand in WebAPI perRequest to handle Circular errors在每个请求的 Web API 中使用 Autofac 按需解析来处理循环错误
【发布时间】:2014-10-27 11:27:52
【问题描述】:

我在基本级别使用 autofac 来处理依赖注入。我现在的配置很简单:

builder.RegisterType<TestDbContext>().As<DbContext, TestDbContext>().InstancePerRequest();
builder.RegisterType<UserRepository>().As<IUserRepository>().InstancePerRequest();
builder.RegisterType<TestRepository>().As<ITestRepository>().InstancePerRequest();

我的问题有点与:'Autofac Circular Component Dependency Detected' Error

我不想得到 Curcular 组件依赖错误,所以我不将 IUserRepository 包含到 ITestRepository 构造函数中(它包含在相反的方向)。

我想使用上述问题答案中的第二个建议。如何对我的TestRepository 进行编码以按需使用UserRepository?我尝试使用 BeginLifetimeScope 进行以下尝试:

public class TestRepository : ITestRepository
{
    public TestRepository()
    {
    }

    public void Test()
    {
        using (var scope = AutofacConfig.Container.BeginLifetimeScope())
        {
            var scopeUserRepo = scope.Resolve<IUserRepository>();
        }
    }
}

但我得到以下异常:

No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the 
instance was requested. This generally indicates that a component registered as 
per-HTTP request is being requested by a SingleInstance() component (or a similar 
scenario.) Under the web integration always request dependencies from the 
DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the 
container itself.

【问题讨论】:

  • 您也可以尝试在 Autofac 中使用 Func 支持:所以在您的 public TestRepository(Func&lt;IUserRepository&gt; userRepositoryCreator) 和您的 Test() 方法中只需写:var scopeUserRepo = userRepositoryCreator();
  • 好吧,如果我有这些循环错误,我有点想我的设计模式一定是错误的;)虽然使用Lazy&lt;IUserRepository&gt; 有一个简单的解决方案,但感谢您的建议

标签: asp.net-web-api autofac


【解决方案1】:

您不能只在 Web API 中开始生命周期范围。 请求生命周期范围随请求消息一起移动。通过像这样手动创建请求生命周期范围,您将不会获得您正在寻找的结果 - 尤其是如果您具有每个请求的生命周期范围依赖项,因为您正在创建的范围将与实际请求生命周期不同。你不会得到你应该得到的终生分享。

There is a detailed FAQ about troubleshooting per-request lifetime scope issues 这应该可以帮助您上路。你可能也对the documentation on properly handling circular dependencies in Autofac感兴趣。

【讨论】:

    【解决方案2】:

    您可以在构造函数中使用注入的 ILifetimeScope:

    public class TestRepository : ITestRepository
    {
        private ILifetimeScope _scope;
    
        public TestRepository(ILifetimeScope scope)
        {
            _scope = scope;
        }
    
        public void Test()
        {
          var scopeUserRepo = _scope.Resolve<IUserRepository>();
        }
    }
    

    【讨论】:

    • 我知道,但我认为这是最糟糕的情况。我可以在构造函数中使用 Lazy ,它也可以工作,但这也不是最好的解决方案。
    • 我只是重写你以前的代码以避免 autofac 错误。我没有说这是最好的解决方案。正确的解决方案应该是重构您的代码设计,但您没有在问题中提供它。
    猜你喜欢
    • 1970-01-01
    • 2014-04-24
    • 1970-01-01
    • 2013-12-27
    • 1970-01-01
    • 1970-01-01
    • 2018-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多