Autofac ResolvedParameter/ComponentContext不起作用 [英] Autofac ResolvedParameter/ComponentContext not working

查看:133
本文介绍了Autofac ResolvedParameter/ComponentContext不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将asp.net coreEntity Framework Core一起使用.我的情况是,我想在运行时根据HttpContext查询字符串值更改连接字符串.

I am using asp.net core along with Entity Framework Core. My scenario here is, I want to change the connection string at runtime based on HttpContext query string value.

我正在尝试将ResolvedParameterReflection components传递为已记录.但是,当我解决此问题时,它没有被注册.在下面,我附上了我的代码段.

I am trying to pass ResolvedParameter with Reflection components as documented. But, It is not getting registered when I resolve this. Here below, I have attached my code snippet.

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

    //..
    //..
}

在运行时,我遇到了错误.

During runtime, I am getting below error.

处理请求时发生未处理的异常.

An unhandled exception occurred while processing the request.

DependencyResolutionException:找不到与之相关的构造函数 类型上的"Autofac.Core.Activators.Reflection.DefaultConstructorFinder" 可以使用"AppDbContext"调用 服务和参数:无法解析参数 'Microsoft.EntityFrameworkCore.DbContextOptions 1[AppDbContext] options' of constructor 'Void .ctor(Microsoft.EntityFrameworkCore.DbContextOptions 1 [AppDbContext])'. Autofac.Core.Activators.Reflection.ReflectionActivator.GetValidConstructorBindings(ConstructorInfo [] availableConstructors,IComponentContext上下文, IEnumerable参数)

DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'AppDbContext' can be invoked with the available services and parameters: Cannot resolve parameter 'Microsoft.EntityFrameworkCore.DbContextOptions1[AppDbContext] options' of constructor 'Void .ctor(Microsoft.EntityFrameworkCore.DbContextOptions1[AppDbContext])'. Autofac.Core.Activators.Reflection.ReflectionActivator.GetValidConstructorBindings(ConstructorInfo[] availableConstructors, IComponentContext context, IEnumerable parameters)

我已经尝试在此处回答 ..但无法正常工作.

I have tried as answered here..but, not working.

推荐答案

我已经解决了此问题,方法是作为Guru Stron的注释和后续更改进行更改.这是我的零钱.

I have resolved this issue by doing change as Guru Stron's comment and subsequent changes. Here is my change.

步骤1:更改了Autofac注册类别,如下所示:

Step 1: Changed Autofac Registration class as below:

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,则也 确保您的DbContext类型接受DbContextOptions 对象在其构造函数中并将其传递给基本构造函数 DbContext.

InvalidOperationException: No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext.

通过在AppDbContext类中添加以下代码来解决上述错误.

By add below code in AppDbContext class to resolve above error.

步骤2:修改了AppDbContext(添加了OnConfiguring()方法)

Step 2: Modified AppDbContext (Added OnConfiguring() method)

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

    //..
    //..
}

这篇关于Autofac ResolvedParameter/ComponentContext不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆