我发现WebApi集成存在问题。
示例项目:https://github.com/VKrol/WebApplication19
尝试创建对“〜/ api / values”的请求,尽管类Foo已注册为InstancePerLifetimeScope,但Foo类已经实例化了两次。请注意,我解决了Application_AcquireRequestState中的第一个实例,并且第二个实例已在ValuesController构造函数中注入。 我认为这是一个错误。
感谢。
答案 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 { } }
}