MeT*_*tus 1 c# dependency-injection autofac asp.net-web-api2
我有以下代码来构建依赖项:
private static void InitializeContainer(HttpConfiguration config)
{
var builder = new ContainerBuilder();
var controllers = AssemblyUtils.GetAssemblies(true);
controllers.Add(Assembly.GetExecutingAssembly());
builder.RegisterApiControllers(controllers.ToArray()).PropertiesAutowired();
builder
.RegisterAssemblyTypes(
new List<Assembly>(AssemblyUtils.GetAssemblies(false))
{
Assembly.GetExecutingAssembly()
}.ToArray())
.Where(t =>
t.GetCustomAttributes(typeof(IocContainerMarkerAttribute), false).Any() ||
t.IsSubclassOf(typeof(HandlerAspectAttribute)) ||
typeof(ICoreContract).IsAssignableFrom(t))
.AsImplementedInterfaces().InstancePerDependency()
.PropertiesAutowired().OwnedByLifetimeScope();
var container = builder.Build();
GlobalConfiguration.Configuration.DependencyResolver =
new AutofacWebApiDependencyResolver(container);
config.DependencyResolver =
GlobalConfiguration.Configuration.DependencyResolver;
}
Run Code Online (Sandbox Code Playgroud)
处理程序:
public class ArchieveDocumentCommandHandler
: IHandler<ArchieveDocumentCommand>, IDisposable
{
public IServiceMessageDispatcher Dispatcher { get; set; }
public IDocumentRepository DocumentRepository { get; set; }
public IFileSystemProvider FileSystemProvider { get; set; }
public ICoreSettingRepository CoreSettingRepository { get; set; }
public void Handles(ArchieveDocumentCommand message) { }
public void Dispose() { }
}
Run Code Online (Sandbox Code Playgroud)
但是不知何故 AutofacDispose在请求完成后没有调用对象中的方法。我阅读了生命周期范围,但由于在这种情况下是 Autofac 管理范围,我无法理解发生了什么。
我在这里做错了吗?
更新
public class CommandsController : ApiController
{
[HttpPost]
public HttpResponseMessage Deliver()
{
...
var handler = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(ICommandValidator<>).MakeGenericType(message.GetType()));
if (handler == null)
{
return new Dictionary<string, string>();
}
return (Dictionary<string, string>)handler.GetType()
.InvokeMember("ValidateCommand", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, handler, new object[] { message });
}
}
Run Code Online (Sandbox Code Playgroud)
另外我使用的 autofac web api 版本是: 3.1.1 这也破坏了一些现有的功能:
这样的控制器:
public class AProtectedReadModelController : ApiController
{ }
public class AssessmentController : AProtectedReadModelController
{
[Route("queries/risk/assessment")]
[HttpGet]
public ProcessInitialScreenModel GetProcessInitialScreen()
{
return ...;
}
}
Run Code Online (Sandbox Code Playgroud)
未加载。
您面临的挑战是因为您试图DependencyResolver在请求生命周期范围之外解析对象,而不是使用请求生命周期范围。
当您使用 Web API 时,“请求生命周期范围”由入站请求消息管理。当您从根解决某些DependencyResolver问题时,它会在应用程序/顶级解决,而不是作为请求的一部分。这就是为什么你没有看到任何东西被处置——因为拥有生命周期范围没有被处置,因为拥有生命周期范围是在根级别。
我对请求生命周期范围进行了长时间的讨论,作为对这个问题的回答:Transitioning to AutofacWebApiDependencyResolver from MVC's DependencyResolver - Where is .Current?
虽然另一个问题涉及测试场景,但它的答案仍然成立 - 如果您需要手动解决某些问题(如果可能的话,我建议不要这样做 - 服务位置不是那么好),那么您需要这样做与请求消息关联的请求范围。
// In the controller...
var validatorType = typeof(ICommandValidator<>)
.MakeGenericType(message.GetType());
var handler = this.Request
.GetDependencyScope()
.GetService(validatorType);
Run Code Online (Sandbox Code Playgroud)