Autofac范围问题
我想让autofac工作,但我的unitofwork /用户管理器类有问题。
最初我将我的工作单元设置为每个请求实例,如下所示:
builder.RegisterType<UnitOfWork>().As().InstancePerRequest();
但在我的StartupConfig.cs中,我试图像这样设置oAuth:
private static OAuthAuthorizationServerOptions ConfigureOAuthTokenGeneration(IAppBuilder app, ILifetimeScope scope) { var t = scope.Resolve(); // Get our providers var authProvider = scope.Resolve(); var refreshTokenProvider = scope.Resolve(); // Create our OAuth options return new OAuthAuthorizationServerOptions() { AllowInsecureHttp = true, // TODO: Remove this line TokenEndpointPath = new PathString("/oauth/access_token"), AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), AccessTokenFormat = new Business.Authentication.JwtFormat("https://localhost:62668"), Provider = authProvider, RefreshTokenProvider = refreshTokenProvider }; }
范围是通过以下方式获得的:
var scope = config.DependencyResolver.GetRootLifetimeScope();
因此,我无法将InstancePerRequest用于UnitOfWork ,而是将其更改为:
builder.RegisterType<UnitOfWork>().As().InstancePerLifetimeScope();
现在应用程序实际运行,但是我的UserProvider出现了一个新错误,它实例化如下:
builder.RegisterType().As().InstancePerRequest();
但如果我运行它,我会收到此错误:
从请求实例的作用域中看不到具有与“AutofacWebRequest”匹配的标记的作用域。
如果在执行Web应用程序期间看到此情况,则通常表示SingleInstance()组件(或类似方案)正在请求按HTTP请求注册的组件。 在Web集成下,始终从依赖项解析程序或请求生存期范围请求依赖项,而不是从容器本身请求。
这实际上是由行调用的:
var authProvider = scope.Resolve();
在我的StartupConfig.cs中 。 OAuthProvider确实需要UserProvider ,签名如下所示:
public OAuthProvider(IAdvancedEncryptionStandardProvider helper, IUserProvider userProvider) { this._helper = helper; this._userProvider = userProvider; }
因为这不在“请求”中,我改变了UserProvider ,就像这样解决:
builder.RegisterType().As().InstancePerLifetimeScope();
现在匹配UnitOfWork ,项目将加载。 但是,如果我有一个尝试做两件事的接口(获取当前用户并列出所有用户),它会创建2个请求,同时创建UserController的新实例:
public UsersController(IUserProvider provider) { this._provider = provider; }
而这又试图创建UserProvider的 2个实例。 这会引发错误:
在创建模型时不能使用上下文。 如果在OnModelCreating方法内部使用上下文,或者同时由多个线程访问相同的上下文实例,则可能抛出此exception。 请注意,DbContext和相关类的实例成员不保证是线程安全的。
所以,我想我需要知道如何解决这个问题。 这就像我需要2个范围,一个用于应用程序的开始,然后另一个用于其他一切。 谁能帮我这个?
问题
因为,在OWIN中间件注册时,您需要提供OAuthAuthorizationServerOptions
的实例,因此无法根据HTTP请求解析Provider
和RefreshTokenProvider
属性。
我们需要的是一种为每个HTTP请求创建OAuthAuthorizationServerOptions
的方法。 通过扩展,相同的概念将适用于OAuthAuthorizationServerMiddleware
。
可能的解决方案
这正是AutofacMiddleware
所做的; 它通过在存储在OWIN上下文中的生命周期范围的HTTP请求期间解析它来包装OWIN中间件,然后执行它。 这意味着我们现在可以为每个HTTP请求实例化一个新的OAuthAuthorizationServerMiddleware
。
如文档中所述 ,当您在Startup
类中使用app.UseAutofacMiddleware(container)
时,Autofac会做两件事 :
然后,解决方案是在Autofac容器中注册OAuthAuthorizationServerMiddleware
及其所有依赖项,并为每个请求自动解析并执行。
OAuthAuthorizationServerMiddleware
有3个依赖项:
我们必须在容器中注册最后两个依赖项和中间件本身。 我们来看看它的外观:
免责声明:我没有尝试下面的代码
// Here go all the registrations associated with the `Provider` // and `RefreshTokenProvider` properties with the appropriate lifetimes builder .RegisterInstance(app) .As(); builder .Register(x => new OAuthAuthorizationServerOptions { AllowInsecureHttp = true, // TODO: Remove this line TokenEndpointPath = new PathString("/oauth/access_token"), AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), AccessTokenFormat = new Business.Authentication.JwtFormat("https://localhost:62668"), Provider = x.Resolve(), RefreshTokenProvider = x.Resolve() }) .AsSelf() // InstancePerDependency is same as InstancePerLifetimeScope // in this case since the middleware will get resolved exactly one // time per HTTP request anyway .InstancePerDependency(); builder.RegisterType();
控制中间件订单
虽然这可能有效,但它可能不适合您的需求,因为OAuth中间件将在您调用app.UseAutofacMiddleware(container)
的OWIN管道中注册。
如果您想要更多地控制中间件订单,可以将Autofac生命周期范围创建与OWIN管道中的中间件注册分开 :
免责声明:我没有尝试下面的代码
上述就是C#学习教程:Autofac范围问题分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
// creates the per HTTP request lifetime scope app.UseAutofacLifetimeScopeInjector(container); // "usual" OWIN middlewares registrations app.UseFoo(); // now use one from the container app.UseMiddlewareFromContainer(); // other "usual" OWIN middlewares registrations app.UseBar();
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/953896.html