[英]Autofac ResolvedParameter/ComponentContext not working
我正在使用asp.net core
和Entity Framework Core
。 我的场景是,我想在运行时根据HttpContext
查询字符串值更改连接字符串。
我正在尝试将ResolvedParameter
与文档中的Reflection components
一起传递。 但是,当我解决这个问题时,它没有被注册。 在下面,我附上了我的代码片段。
Autofac注册class:
public class DependencyRegistrar : IDependencyRegistrar
{
public virtual void Register(ContainerBuilder builder)
{
builder.RegisterType(typeof(DbContextOptionsFactory))
.As(typeof(IDbContextOptionsFactory))
.InstancePerRequest();
builder.RegisterType<AppDbContext>()
.As(typeof(IDbContext))
.WithParameter(
new ResolvedParameter(
(pi, cc) => pi.Name == "options",
(pi, cc) => cc.Resolve<IDbContextOptionsFactory>().Get()));
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.SingleInstance();
}
}
public interface IDbContextOptionsFactory
{
DbContextOptions<AppDbContext> Get();
}
public class DbContextOptionsFactory : IDbContextOptionsFactory
{
public DbContextOptions<AppDbContext> Get()
{
try
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile("appsettings.json")
.Build();
var builder = new DbContextOptionsBuilder<AppDbContext>();
if (EngineContext.Current.Resolve<IHttpContextAccessor>().HttpContext.Request.QueryString.ToString().ToLower().Contains("app1"))
DbContextConfigurer.Configure(builder, configuration.GetConnectionString("app1"));
else if (EngineContext.Current.Resolve<IHttpContextAccessor>().HttpContext.Request.QueryString.ToString().ToLower().Contains("app2"))
DbContextConfigurer.Configure(builder, configuration.GetConnectionString("app2"));
return builder.Options;
}
catch (Exception)
{
throw;
}
}
}
public class DbContextConfigurer
{
public static void Configure(DbContextOptionsBuilder<AppDbContext> builder, string connectionString)
{
builder.UseSqlServer(connectionString);
}
}
应用数据库上下文:
public class AppDbContext : DbContext, IDbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
Assembly assemblyWithConfigurations = typeof(IDbContext).Assembly;
builder.ApplyConfigurationsFromAssembly(assemblyWithConfigurations);
}
//..
//..
}
在运行时,我遇到错误。
处理请求时发生未处理的异常。
DependencyResolutionException:无法使用可用的服务和参数调用类型为“AppDbContext”的“Autofac.Core.Activators.Reflection.DefaultConstructorFinder”的构造函数:无法解析参数“Microsoft.EntityFrameworkCore.DbContextOptions
1[AppDbContext] options' of constructor 'Void.ctor(Microsoft.EntityFrameworkCore.DbContextOptions
1[AppDbContext])'。 Autofac.Core.Activators.Reflection.ReflectionActivator.GetValidConstructorBindings(ConstructorInfo[] availableConstructors, IComponentContext context, IEnumerable parameters)
我已经尝试过这里的回答..但是,没有用。
我已经通过按照 Guru Stron 的评论和后续更改进行更改来解决此问题。 这是我的零钱。
第 1 步:更改 Autofac 注册 class 如下:
public class DependencyRegistrar : IDependencyRegistrar
{
public virtual void Register(ContainerBuilder builder)
{
//Removed this code
//builder.RegisterType(typeof(DbContextOptionsFactory))
// .As(typeof(IDbContextOptionsFactory))
// .InstancePerRequest();
//Added this code
builder.Register(c => c.Resolve<IDbContextOptionsFactory>().Get())
.InstancePerDependency(); // <-- Changed this line
builder.RegisterType<AppDbContext>()
.As(typeof(IDbContext))
.WithParameter(
new ResolvedParameter(
(pi, cc) => pi.Name == "options",
(pi, cc) => cc.Resolve<IDbContextOptionsFactory>().Get()))
.InstancePerDependency(); // <-- Added this line
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.InstancePerDependency(); // <-- Changed this line
}
}
现在,如果您收到错误消息:
InvalidOperationException:没有为此 DbContext 配置数据库提供程序。 可以通过覆盖 DbContext.OnConfiguring 方法或在应用程序服务提供者上使用 AddDbContext 来配置提供者。 如果使用了 AddDbContext,则还要确保您的 DbContext 类型在其构造函数中接受 DbContextOptions object 并将其传递给 DbContext 的基本构造函数。
通过在AppDbContext
class 中添加以下代码来解决上述错误。
第 2 步:修改AppDbContext
(添加OnConfiguring()
方法)
public class AppDbContext : DbContext, IDbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
Assembly assemblyWithConfigurations = typeof(IDbContext).Assembly;
builder.ApplyConfigurationsFromAssembly(assemblyWithConfigurations);
}
//Added this method
protected override void OnConfiguring(DbContextOptionsBuilder dbContextOptionsBuilder)
{
base.OnConfiguring(dbContextOptionsBuilder);
}
//..
//..
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.