我需要在我的身份验证处理程序中获取IUserService类型的已注册实例。
// Register services
// Build the container.
var containr = builder.Build();
var resolver = new AutofacWebApiDependencyResolver(container);
configuration.DependencyResolver = resolver;
当我现在运行这行代码时:
var userService = configuration.DependencyResolver.GetService(typeof (IUserService)) as IUserService;
我得到了这个例外:
An exception of type 'Autofac.Core.DependencyResolutionException' occurred in Autofac.dll but was not handled in user code
Additional information: 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.
我不想手动创建用户服务,因为我必须手动解决依赖类...
当我不在请求中时,如何获得某项服务? Dependency.Resolver未知/无法解决以某种方式使用它。
更新
我现在将服务注册更改为:
builder.RegisterType<UserService>()
.As<IUserService>()
.WithParameter(namedParameter)
.InstancePerLifetimeScope();
而不是InstancePerRequestApi()
并解决用户服务:
var resolver = (AutofacWebApiDependencyResolver)config.DependencyResolver;
var bla = resolver.GetRootLifetimeScope();
IUserService userService = bla.Resolve<IUserService>(); // Woot!
这有效,但我以前的InstancePerApiRequest怎么样?我也想保留它!
更新
public static void Register(HttpSelfHostConfiguration config)
{
config.MapHttpAttributeRoutes();
var resolver = (AutofacWebApiDependencyResolver)config.DependencyResolver;
var scope = resolver.GetRootLifetimeScope();
var userService = scope.Resolve<IUserService>();
scope.Dispose();
var authenticationHandler = new AuthenticationHandler(userService);
var tokenHandler = new TokenHandler();
config.MessageHandlers.Add(new HttpsHandler());
config.MessageHandlers.Add(new AllowCommonVerbsHandler());
config.MessageHandlers.Add(authenticationHandler);
config.MessageHandlers.Add(tokenHandler);
config.Routes.MapHttpRoute(
name: "Authentication",
routeTemplate: "api/users/{id}",
defaults: new { controller = "users", id = RouteParameter.Optional },
constraints: null,
handler: authenticationHandler // Put this handler later on the DefaultApi
);
config.Routes.MapHttpRoute(
name: "TokenApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional },
constraints: null,
handler: tokenHandler
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { controller = "Home", action = "Start" }
);
var jsonFormatter = new JsonMediaTypeFormatter();
config.Services.Replace(typeof(IContentNegotiator), new JsonContentNegotiator(jsonFormatter));
}
答案 0 :(得分:1)
我假设您的身份验证处理程序是DelegatingHandler。如果是这种情况,您可以使用以下代码访问当前请求的生命周期范围:
var scope = request.GetDependencyScope();
var requestScope = scope.GetRequestLifetimeScope();
在上面的代码request
中,HttpRequestMessage
实例传递给SendAsync
的{{1}}方法。
在这种情况下,您将无法拥有构造函数依赖项。在DelegatingHandler
方法内部,使用上面提供的代码在需要使用时解析SendAsync
实例。
要为处理程序创建测试,您需要模拟Web API依赖范围。
IUserService
请参阅var builder = new ContainerBuilder();
// Configure container for test.
var container = builder.Build();
var request = new HttpRequestMessage();
var lifetimeScope = container.BeginLifetimeScope(AutofacWebApiDependencyResolver.ApiRequestTag);
var scope = new AutofacWebApiDependencyScope(lifetimeScope);
request.Properties.Add(HttpPropertyKeys.DependencyScope, scope);
了解如何对HttpMessageInvoker
进行单元测试。
答案 1 :(得分:0)
我认为您在使用IRepository
时创建类的对象时可能忘记添加readonly,或者在声明构造函数之前可能忘记了访问修饰符。希望这对你有帮助。