Autofac + WebApi。 InstancePerLifetimeScope依赖项的双重实例化

时间:2015-01-14 15:09:21

标签: asp.net-web-api autofac asp.net-web-api2

我发现WebApi集成存在问题。

示例项目:https://github.com/VKrol/WebApplication19

尝试创建对“〜/ api / values”的请求,尽管类Foo已注册为InstancePerLifetimeScope,但Foo类已经实例化了两次。请注意,我解决了Application_AcquireRequestState中的第一个实例,并且第二个实例已在ValuesController构造函数中注入。 我认为这是一个错误。

感谢。

2 个答案:

答案 0 :(得分:3)

简短版本是:您正在使用Web API项目但是您正在尝试使用MVC依赖项解析程序。您还没有在演示项目中的任何位置设置MVC依赖项解析程序

当您的事件处理程序调用{​​{1}}时,它将使用默认的MVC依赖项解析程序,不是Autofac

DependencyResolver.Current.GetService<Foo>();

如果您查看public class WebApiApplication : HttpApplication { protected void Application_Start() { GlobalConfiguration.Configure(WebApiConfig.Register); var builder = new ContainerBuilder(); var config = GlobalConfiguration.Configuration; builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); builder.RegisterType<Foo>().AsSelf().InstancePerLifetimeScope(); var container = builder.Build(); // Here's where the Web API resolver is set up... config.DependencyResolver = new AutofacWebApiDependencyResolver(container); } protected virtual void Application_AcquireRequestState(object sender, EventArgs e) { // ...but this call is using the MVC dependency resolver! var foo = DependencyResolver.Current.GetService<Foo>(); } } 的作用,则会根据请求的类型调用System.Web.Mvc.DependencyResolver.DefaultDependencyResolver。在这种情况下,您的Activator.CreateInstance(type)类型。

所以 - 您将获得两个不同的实例,因为您的依赖项解析器设置不正确。

如果您想使用MVC依赖项解析程序,可以通过设置per the documentation来自由地执行此操作。请注意,这将共享容器,但不会共享请求生存期范围机制。如果Web API请求进入,它不一定以与MVC相同的方式创建请求生存期范围,因此每个请求依赖项将无法按您的思路运行。在Web API和that's also in the docs中处理请求生存期的方法不同。

如果您使用的是非OWIN Web API,可以调用Foo来获取使用Autofac设置的Web API依赖关系解析器。但是,您无法从此获取每个请求的范围,也无法解析每个请求的依赖关系。但是,如果您必须手动解析服务,那就是您的工作方式。

如果您选择切换到OWIN Web API,则没有全局配置或全局依赖项解析程序。然后,您将被迫使用附加到请求消息的GlobalConfiguration.Configuration.DependencyResolver或使用DependencyScope之类的机制。

答案 1 :(得分:0)

我不认为这是Autofac中的错误。

LifeTimeScopes are dependant on the scope in which they were resolved。在您的情况下,我认为您正在两个不同的范围内解析Foo。在应用程序根范围(Application_AcquireRequestState)及其子范围(ValuesController)中。 Autofac不允许从子范围进行解析,因此您的服务请求都会被独立解决。

AcquireRequestState中注释掉该决议后,我在您的项目中添加了另一个类NClass,请求Foo,我看到Foo仅解析一次预期。

public class ValuesController : ApiController {
    private readonly Foo _foo;
    private NClass _nclass;

    public ValuesController(Foo foo,NClass nClass) {
        _foo = foo;
        _nclass = nClass;
    }

    public IEnumerable<string> Get() {
        return new[] { _foo.Id.ToString(),  _nclass.Id.ToString()};
    }
}
public class NClass
{
    private Foo _foo;
    public NClass(Foo foo) { _foo = foo; }
    public int Id { get  {  return _foo.Id; } set { } }
}