gro*_*kky 3 c# autofac asp.net-core
我正在使用 ASP.NET Core 和 Autofac。几乎所有内容都是按照生命周期范围(“每个请求”)注册的。所以我的数据库上下文DbContext在整个请求中是同一个实例。
不过我有一个单例,它也依赖于DbContext. 为了避免强制依赖,它被注入为,这意味着每次都有Func<Owned<DbContext>>一个新实例。DbContext
问题是我需要与请求期间其他地方相同的实例,而不是新的实例。
我想避免强制依赖错误,但我也想要相同的实例。可以通过标记或自定义注册实现这一点吗?
从评论来看,最不“架构”痛苦的方法可能是创建您自己的Scoped<T>类,它将从当前解析 DbContextHttpContext
// Use an interface, so we don't have infrastructure dependencies in our domain
public interface IScoped<T> where T : class
{
T Instance { get; }
}
// Register as singleton too.
public sealed class Scoped<T> : IScoped<T> where T : class
{
private readonly IHttpContextAccessor contextAccessor;
private HttpContext HttpContext { get; } => contextAccessor.HttpContext;
public T Instance { get; } => HttpContext.RequestServices.GetService<T>();
public Scoped(IHttpContextAccessor contextAccessor)
{
this.contextAccessor = contextAccessor ?? throw new ArgumentNullException(nameof(contextAccessor));
}
}
Run Code Online (Sandbox Code Playgroud)
将其注册为
// Microsoft.Extensions.DependencyInjection
services.AddSingleton(typeof(IScoped<>), typeof(Scoped<>);
// Autofac
containerBuilder.RegisterType(typeof(Scoped<>))
.As(typeof(IScoped<>));
Run Code Online (Sandbox Code Playgroud)
然后将其注入您的验证器服务中。
public class CustomerValidator: AbstractValidator<Customer>
{
private readonly IScoped<AppDbContext> scopedContext;
protected AppDbContext DbContext { get } => scopedContext.Instance;
public CustomValidator(IScoped<AppDbContext> scopedContext)
{
this.scopedContext = scopedContext ?? throw new ArgumentNullException(nameof(scopedContext));
// Access DbContext via this.DbContext
}
}
Run Code Online (Sandbox Code Playgroud)
这样您就可以注入任何范围内的服务而无需进一步注册。
Autofac 被认为是“符合者”(请参阅文档)DI,并且与 ASP.NET Core 和 Microsoft.Extensions.DependencyInjection 集成良好。
从文档中
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// Add services to the collection.
services.AddMvc();
// Create the container builder.
var builder = new ContainerBuilder();
// Register dependencies, populate the services from
// the collection, and build the container. If you want
// to dispose of the container at the end of the app,
// be sure to keep a reference to it as a property or field.
builder.RegisterType<MyType>().As<IMyType>();
builder.Populate(services);
this.ApplicationContainer = builder.Build();
// Create the IServiceProvider based on the container.
return new AutofacServiceProvider(this.ApplicationContainer);
}
Run Code Online (Sandbox Code Playgroud)
Startup类和容器的默认用法有一些细微的差别Microsoft.Extensions.DependencyInjection。
ConfigureServices不再是了void,它又回来了IServiceProvider。这将告诉 ASP.NET Core 使用返回的提供程序而不是DefaultServiceProvider来自Microsoft.Extensions.DependencyInjection.new AutofacServiceProvider(this.ApplicationContainer)它是根容器。这对于让 ASP.NET Core 在 ASP.NET Core 中的任何地方使用容器非常重要,甚至在通过HttpContext.RequestedServices.
因此,您不能.InstancePerRequest()在 Autofac 中使用生命周期,因为 Autofac 无法控制创建范围,并且只有 ASP.NET Core 可以做到这一点。因此没有简单的方法可以让 ASP.NET Core 使用 Autofac 自己的 Request 生命周期。
相反,ASP.NET Core 将创建一个新作用域(使用IServiceScopeFactory.CreateScope())并使用 Autofac 的作用域容器来解析每个请求的依赖关系。
| 归档时间: |
|
| 查看次数: |
1721 次 |
| 最近记录: |