Asp.net web api 注册表状态可以';t在Autofac中使用IntstancePerRequestMode注册

Asp.net web api 注册表状态可以';t在Autofac中使用IntstancePerRequestMode注册,asp.net-web-api,autofac,Asp.net Web Api,Autofac,我在WebAPI委托处理程序中有一个代码,用于从请求头提取数据。 但是,我无法在Autofac容器中注册实例,因为Autofac容器只需要SingleInstance public class ExtractUserNameMessageHandler : DelegatingHandler { protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage

我在WebAPI委托处理程序中有一个代码,用于从请求头提取数据。 但是,我无法在Autofac容器中注册实例,因为Autofac容器只需要SingleInstance

            public class ExtractUserNameMessageHandler : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
var userNameFromFrontEnd = request.GetDependencyScope().GetService(typeof (IUserNameFromFrontEnd));
        if (userNameFromFrontEnd == null)
        {
            var updatedContainerBuilder = new ContainerBuilder();
            userNameFromFrontEnd = ExtractUserName(request);
            if (userNameFromFrontEnd == null)
            {
                throw new Exception("We've got a request without UserName header");
            }
            updatedContainerBuilder.RegisterInstance(userNameFromFrontEnd)
                .As<IUserNameFromFrontEnd>()
                .InstancePerRequest();
            var autofacDependencyResolver = GlobalConfiguration.Configuration.DependencyResolver as AutofacWebApiDependencyResolver;
            if (autofacDependencyResolver == null)
            {
                throw new Exception("We can work with Autofac DI container");
            }
            updatedContainerBuilder.Update(autofacDependencyResolver.Container as IContainer);
        }
public类ExtractUserNameMessageHandler:DelegatingHandler
{
受保护的异步覆盖任务SendAsync(HttpRequestMessage请求,CancellationToken CancellationToken)
var userNameFromFrontEnd=request.GetDependencyScope().GetService(typeof(IUserNameFromFrontEnd));
if(userNameFromFrontEnd==null)
{
var updatedContainerBuilder=新的ContainerBuilder();
userNameFromFrontEnd=ExtractUserName(请求);
if(userNameFromFrontEnd==null)
{
抛出新异常(“我们收到一个没有用户名头的请求”);
}
updatedContainerBuilder.RegisterInstance(用户名fromFrontEnd)
.As()
.InstancePerRequest();
var autofacDependencyResolver=全局配置.Configuration.DependencyResolver作为AutofacWebApiDependencyResolver;
如果(autofacDependencyResolver==null)
{
抛出新异常(“我们可以使用Autofac DI容器”);
}
updatedContainerBuilder.Update(autofacDependencyResolver.Container作为IContainer);
}
当我尝试更新容器时,我得到一个异常消息-注册只能支持singleinstance()共享

这意味着什么?我不明白为什么我们有这个限制。但无论如何,我的第一个目标是用新的依赖项更新容器。 有人有想法吗?

(注:)

当您注册一个特定的实例时,它实际上是一个单实例——它是一个实例,即您提供的实例

当您尝试为其分配
InstancePerRequest
或实际上是除
SingleInstance
之外的任何其他生存期范围时,这在逻辑上是没有意义的,因为您不会为每个请求(或其他任何请求)获得不同的实例。您将获得与您注册的实例完全相同的实例,即singleton

异常消息试图告诉您如何避免错误的期望:即使您告诉它,它也不能为每个请求提供不同的实例,因为您没有告诉它如何创建新实例,而是提供了一个特定实例

如果每个生命周期范围/请求/任何内容都需要不同的对象实例,则需要注册类型、委托或告诉Autofac如何创建新实例的其他内容。

这意味着,如果您希望每个请求的
iUserName与Frontend
不同,则需要将该逻辑从
DelegatingHandler
移到Autofac注册委托中

// Make sure to register the HttpRequestMessage in the container
// so you can resolve it...
builder.RegisterHttpRequestMessage(httpConfiguration);

// Then, whilst building your root container...
builder
  .Register(ctx =>
   {
     var request = ctx.Resolve<HttpRequestMessage>();
     return ExtractUserName(request);
   })
  .As<IUserNameFromFrontEnd>()
  .InstancePerRequest();
AutofacDependencyResolver
是创建请求生存期范围并将其交给Web API的工具。关键方法是
BeginScope

public IDependencyScope BeginScope()
{
  var lifetimeScope = _container.BeginLifetimeScope(MatchingScopeLifetimeTags.RequestLifetimeScopeTag);
  return new AutofacWebApiDependencyScope(lifetimeScope);
}
如果您创建自己的
AutofacDependencyResolver
,则可以修改作用域的创建方式:

public IDependencyScope BeginScope()
{
  var lifetimeScope = _container.BeginLifetimeScope(
    MatchingScopeLifetimeTags.RequestLifetimeScopeTag,
    builder => builder.RegisterInstance(myfoo).As<IFoo>());
  return new AutofacWebApiDependencyScope(lifetimeScope);
}
public idependencycoscope BeginScope()
{
var lifetimeScope=\u container.BeginLifetimeScope(
MatchingScopeLifetimeTags.RequestLifetimeScopeTag,
builder=>builder.RegisterInstance(myfoo.As());
返回新的AutofacWebApidencyScope(lifetimeScope);
}
目前,在Autofac Web API集成中,这不是一个明确支持的扩展点-这就是您必须创建自己的解析器的原因


但是,要解决您试图解决的问题,这似乎有些过分。我强烈建议只向Autofac注册代理,而不是尝试更新现有的容器或作用域。使用阻力最小的路径,您会幸运得多。

很抱歉,这不是真的。我想设置con每个请求都有自己的实例(这就是我使用InstancePerRequest的原因。如果我为全局作用域注册一个实例-我将为所有作用域获得相同的实例-这不是我想要的。如果我可以在RequestScope内注册一个实例-我将绝对满意。但我不能这样做。A为这个问题找到了解决办法,但它不是那么漂亮。我认为(我希望?)沟通有误-我告诉你的是真的,但你可能不希望是真的。我认为挑战在于你问的问题-你问错误消息是什么意思(我解释过)以及如何更新容器(你知道了)。我想你想问的是如何用特定的依赖项更新请求生存期范围,这是一个不同的问题。我会更新我的答案。非常感谢,特拉维斯。我会尝试你的决定。这似乎比我做的要好。此外,还有一个小问题。你对register httpRequestMessage的决定是否适用于中的所有实例“请求范围"?这意味着,我希望在HttpRequestMessageScope内创建的所有对象在作用域内获得相同的依赖关系?如果DI容器在请求作用域内创建三个对象,那么所有这些对象将从FrontEnd获得相同的IUserNames。我希望这是真的,但只是为了澄清。如果您使用每个请求的委托注册范围,那么一个请求中的所有解决方案都将得到相同的实例。我希望这会有所帮助。如果仍然没有意义…也许可以试试看。我想你会得到你期望的结果。
public IDependencyScope BeginScope()
{
  var lifetimeScope = _container.BeginLifetimeScope(
    MatchingScopeLifetimeTags.RequestLifetimeScopeTag,
    builder => builder.RegisterInstance(myfoo).As<IFoo>());
  return new AutofacWebApiDependencyScope(lifetimeScope);
}