我收到以下异常:
"在类型'NetCore.DAL.EF.Repository.Core.Common.SystemSettingRepository'上找到的'Autofac.Core.Activators.Reflection.DefaultConstructorFinder'的构造函数都不能使用可用的服务和参数调用:\r无法解析参数'NetCore.DAL.EF.DatabaseFactory
1[NetCore.DAL.EF.AppDbContext] databaseFactory' of constructor 'Void .ctor(NetCore.DAL.EF.DatabaseFactory
1[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].目标服务[0]。ServiceType= {Dcs.NetCore.ApplicationCore.BLL.Domain.Features.Common.SystemSettings.ISystemSettingRepository}
autofacServiceProvider.Non-Public members._lifetimeScope.ComponentRegistry.Registrations[28].目标服务[1]。ServiceType= {Dcs.NetCore.Infrastructure.Common.IRepository'1[Dcs.NetCore.ApplicationCore.BLL.Domain.Entities.Common.SystemSetting]}
autofacServiceProvider.Non-Public members._lifetimeScope.ComponentRegistry.Registrations[28].目标服务[2]。ServiceType= {NetCore.DAL.EF.Repositories.Core.Common.SystemSettingRepository}
如您所见,服务已注册。但是,数据库工厂参数不是。这是我的代码:
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()
{ }
该问题是由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();