Autofac ResolvedParameterComponentContext不工作。

问题描述 投票:0回答:1

我使用的是 asp.net core 与...一起 Entity Framework Core. 我的方案是,我想在运行时根据以下内容改变连接字符串。HttpContext 查询字符串值。

我试图通过 ResolvedParameterReflection components 作为 有据可查. 但是,当我解决这个问题时,它没有得到注册。下面,我附上了我的代码片段。

Autofac注册类。

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);
    }
}

AppDbContext:

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.DbContextOptions1[AppDbContext])'。) Autofac.Core.Activators.Reflection.ReflectionActivator.GetValidConstructorBindings(ConstructorInfo[] availableConstructors, IComponentContext context, IEnumerable parameters)

我曾试过 在此回答...但是,没有工作。

c# asp.net-core dependency-injection autofac dbcontext
1个回答
0
投票

我已经解决了这个问题,通过做改变Guru Stron的评论和后续的变化。下面是我的改动。

步骤1.将Autofac注册类改为HttpContext查询字符串值。 更改Autofac注册类如下。

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: No database provider has been configured for this DbContext. 可以通过覆盖DbContext.OnConfiguring方法或使用应用程序服务提供者上的AddDbContext来配置提供者。如果使用AddDbContext,那么还要确保你的DbContext类型在其构造函数中接受一个DbContextOptions对象,并将其传递给DbContext的基础构造函数。

通过在下面的代码中添加 AppDbContext 类来解决上述错误。

第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);
    }

    //..
    //..
}
© www.soinside.com 2019 - 2024. All rights reserved.