封闭泛型类型注册 - Autofac - 无法解析构造函数的参数x

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

我收到以下异常:

“可以使用可用的服务和参数调用在'NetCore.DAL.EF.Repositories.Core.Common.SystemSettingRepository'类型''Autofac.Core.Activators.Reflection.DefaultConstructorFinder'中找到的构造函数:\ r \ n无法解析参数'NetCore.DAL.EF.DatabaseFactory1[NetCore.DAL.EF.AppDbContext] databaseFactory' of constructor 'Void .ctor(NetCore.DAL.EF.DatabaseFactory1 [NetCore.DAL.EF.AppDbContext])'。“

以下是SystemSettingRepository的Autofac注册信息:

autofacServiceProvider.Non-Public members._lifetimeScope.ComponentRegistry.Registrations [28] = {Activator = SystemSettingRepository(ReflectionActivator),Services = [Dcs.NetCore.ApplicationCore.BLL.Domain.Features.Common.SystemSettings.ISystemSettingRepository,Dcs.NetCore.Infrastructure .Common.IRepository`1 [[Dcs.NetCore.ApplicationCore.BLL.Domain.Entities.Common.SystemSetting,Dcs.NetCore.ApplicationCore.BLL,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]],NetCore。 DAL.EF.Repositories.Core.Common.SystemSettingRepository],Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime,Sharing = None,Ownership = OwnedByLifetimeScope}

autofacServiceProvider.Non-Public members._lifetimeScope.ComponentRegistry.Registrations [28] .Target.Services [0] .ServiceType = {Dcs.NetCore.ApplicationCore.BLL.Domain.Features.Common.SystemSettings.ISystemSettingRepository}

autofacServiceProvider.Non-Public members._lifetimeScope.ComponentRegistry.Registrations [28] .Target.Services [1] .ServiceType = {Dcs.NetCore.Infrastructure.Common.IRepository`1 [Dcs.NetCore.ApplicationCore.BLL.Domain.Entities。 Common.SystemSetting]}

autofacServiceProvider.Non-Public members._lifetimeScope.ComponentRegistry.Registrations [28] .Target.Services [2] .ServiceType = {NetCore.DAL.EF.Repositories.Core.Common.SystemSettingRepository}

如您所见,服务已注册。但是,databaseFactory参数不是。这是我的代码:

public class Startup
{
    …
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        …
        return AutofacBuilder();
    }

    private AutofacServiceProvider AutofacBuilder()
    {
        var builder = new ContainerBuilder();
        builder.RegisterModule<AutofacModule_AspNetCore>();
        builder.Populate(_services);
        this.AutofacContainer = builder.Build();
        var autofacServiceProvider = new AutofacServiceProvider(this.AutofacContainer);
        return autofacServiceProvider;
    }
}

public class AutofacModule_AspNetCore : Autofac.Module
{
    protected override void Load(ContainerBuilder builder)
    {
            RegisterDbContexts();
            RegisterComponents();
    }
    private void RegisterComponents()
    {
        _builder.RegisterGeneric(typeof(DatabaseFactory<>))
            .As(typeof(IDatabaseFactory<>))
            .InstancePerDependency();
        _builder.RegisterAssemblyTypes(_assembly)
            .AsClosedTypesOf(typeof(IRepository<>))
            .WithParameter(new ResolvedParameter((p, i) => p.Name == "databaseFactory",
                                                 (p, i) => i.Resolve<DatabaseFactory<AppDbContext>>()))
            //.WithParameter("databaseFactory", new DatabaseFactory<AppDbContext>())
            //.WithParameter(ResolvedParameter//.ForNamed<IDbContext>("coreDomainDbContext"));
            //.WithParameter("databaseFactory", )
            .InstancePerDependency();
    }
    private void RegisterDbContexts()
    {
        RegisterAppDbContextInstance();
    }

    private void RegisterAppDbContextInstance()
    {
        // register DbContextOptionsBuilderHelper
        _builder.RegisterType<AppDbContextOptionsBuilderHelper>()
            .InstancePerDependency();
        // configure DbContextOptions
        var dbContextOptionsBuilderHelper = new AppDbContextOptionsBuilderHelper();
        var dbContextOptionsBuilder = dbContextOptionsBuilderHelper.GetDbContextOptionsBuilder();
        // register DbContext
        _builder.RegisterType<AppDbContext>()
            .WithParameter("options", dbContextOptionsBuilder.Options)
            .InstancePerDependency();
    }
}

public class DatabaseFactory<T> : Disposable, IDatabaseFactory<T>
        where T : DbContext //, new()
{
    private T _dbContext;
    private AppDbContextOptionsBuilderHelper _appDbContextOptionsBuilderHelper;
    private DefaultDbContextOptionsBuilderHelper _defaultDbContextOptionsBuilderHelper;

    public DatabaseFactory()
    {
        this._appDbContextOptionsBuilderHelper = new AppDbContextOptionsBuilderHelper();  // TODO: refactor to ctor injection
        this._defaultDbContextOptionsBuilderHelper = new DefaultDbContextOptionsBuilderHelper();  // TODO: refactor to ctor injection
    }

    public T Get()
    {
        if (_dbContext == null)
            Create();
         return _dbContext;
    }

    private void Create()
    {
        switch (typeof(T).Name)
        {
            case "AppDbContext":
            {
                CreateAppDbContext();
                break;
            }
            case "DefaultDbContext":
            {
                CreateDefaultDbContext();
                break;
            }
        }
    }
    private void CreateAppDbContext()
    {
        var dbContextOptionsBuilder = _appDbContextOptionsBuilderHelper.GetDbContextOptionsBuilder();
        this._dbContext = new AppDbContext(dbContextOptionsBuilder.Options) as T;
    }
    //protected override void DisposeCore()
    //{
    //
        // cref: Autofac.Util.Disposable
        //
        //    //TODO: should I override Autofac.Util.Disposable here?
        //    var msg = "DatabaseFactory.DisposeCore() executing";
        //    if (_dbContext != null)
        //        _dbContext.Dispose();
    //}
}

public partial class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
    { }
    public AppDbContext()
    {}
}

public class SystemSettingRepository : RepositoryBase<SystemSetting, AppDbContext>, ISystemSettingRepository
{
    public SystemSettingRepository(DatabaseFactory<AppDbContext> databaseFactory)
            : base(databaseFactory)
    { }
}

public interface ISystemSettingRepository : IRepository<SystemSetting>
{}

public partial interface IRepository<T> where T : class
{}

public abstract class RepositoryBase<T, U> : IRepositoryBase<T, U>
        where T : class
        where U : DbContext //, new()
{
    private U _dbContext;
    private readonly DbSet<T> _dbset;
    protected RepositoryBase(DatabaseFactory<U> databaseFactory)
    {
        DatabaseFactory = databaseFactory;
        _dbset = DataContext.Set<T>();
    }
    protected virtual DatabaseFactory<U> DatabaseFactory
    {
        get;
        private set;
    }

    protected virtual U DataContext
    {
        get { return _dbContext = DatabaseFactory.Get(); }
    }

    public virtual async Task<T> AddAsync(T dao)
    {
        EntityEntry<T> entityEntry = _dbset.Add(dao);
        var result = await SaveChangesAsync();
        if (result > 0 && entityEntry != null && entityEntry.Entity != null)
            return entityEntry.Entity;
        else
            return null;
    }
}

public interface IRepositoryBase<T, U> 
        where T : class
        where U : DbContext //, new()
{ }
asp.net-core autofac
1个回答
1
投票

问题是由DatabaseFactory<>的注册方式引起的。此类型注册为接口IDatabaseFactory<>。但它在注册存储库时在方法WithParameter()的lambda参数中被解决为:

 _builder.RegisterAssemblyTypes(_assembly)
        .AsClosedTypesOf(typeof(IRepository<>))
        .WithParameter(new ResolvedParameter((p, i) => p.Name == "databaseFactory",
                                             // resolving type it self
                                             // while it was registered as interface
                                             (p, i) => i.Resolve<DatabaseFactory<AppDbContext>>()))

Autofac不知道如何解决它,因为它没有相应的注册。要使代码工作,您可以将DatabaseFactory解析为如下界面:

.WithParameter(new ResolvedParameter((p, i) => p.Name == "databaseFactory",
                                     (p, i) => i.Resolve<IDatabaseFactory<AppDbContext>>()))

或者添加AsSelf()电话注册:

_builder.RegisterGeneric(typeof(DatabaseFactory<>))
        .As(typeof(IDatabaseFactory<>))
        // Register also as DatabaseFactory<>
        .AsSelf()
        .InstancePerDependency();
© www.soinside.com 2019 - 2024. All rights reserved.