Xamarin Forms中Autofac注入双SQLite连接的仓储问题排查
解决Autofac注入双SQLite连接与仓储区分的问题
你的问题核心出在两个地方:双SQLite连接的歧义注册,以及抽象仓储类的错误注册方式。下面一步步帮你修正:
1. 给两个SQLite连接做命名区分
Autofac默认会覆盖同类型的重复注册(或抛出歧义错误),所以得给两个SQLiteAsyncConnection加上唯一标识,用Named方法实现命名注册:
// 注册第一个数据库连接,命名为"FirstDb" builder.Register(c => new SQLiteAsyncConnection(c.Resolve<IDatabaseConfiguration>().GetFirstConnectionPath())) .Named<SQLiteAsyncConnection>("FirstDb") .SingleInstance(); // 注册第二个数据库连接,命名为"SecondDb" builder.Register(c => new SQLiteAsyncConnection(c.Resolve<IDatabaseConfiguration>().GetSecondConnectionPath())) .Named<SQLiteAsyncConnection>("SecondDb") .SingleInstance();
2. 注册具体仓储类而非抽象类
你之前注册抽象的BaseRepository<>是完全错误的——抽象类无法被实例化,Autofac根本没法创建它的实例。应该直接注册你写的两个具体仓储SQLiteRepositoryFirst<>和SQLiteRepositorySecond<>,同时绑定它们对应的命名数据库连接:
// 注册第一个仓储,绑定"FirstDb"连接 builder.RegisterGeneric(typeof(SQLiteRepositoryFirst<>)) .AsImplementedInterfaces() // 告诉Autofac:当构造函数需要SQLiteAsyncConnection时,解析命名为"FirstDb"的实例 .WithParameter( (pi, ctx) => pi.ParameterType == typeof(SQLiteAsyncConnection), (pi, ctx) => ctx.ResolveNamed<SQLiteAsyncConnection>("FirstDb") ) // 给这个仓储实例也加个命名,方便后续注入区分 .Named<IRepository<>>("FirstRepository") .SingleInstance(); // 注册第二个仓储,绑定"SecondDb"连接 builder.RegisterGeneric(typeof(SQLiteRepositorySecond<>)) .AsImplementedInterfaces() .WithParameter( (pi, ctx) => pi.ParameterType == typeof(SQLiteAsyncConnection), (pi, ctx) => ctx.ResolveNamed<SQLiteAsyncConnection>("SecondDb") ) .Named<IRepository<>>("SecondRepository") .SingleInstance();
3. 使用时明确指定要注入的仓储
现在你在ViewModel或其他类中需要使用IRepository<HouseEntity>时,通过[Named]特性告诉Autofac要哪个实例:
public class HouseManagementViewModel { private readonly IRepository<HouseEntity> _firstHouseRepo; private readonly IRepository<HouseEntity> _secondHouseRepo; // 构造函数注入时,用Named特性区分两个仓储 public HouseManagementViewModel( [Named("FirstRepository")] IRepository<HouseEntity> firstHouseRepo, [Named("SecondRepository")] IRepository<HouseEntity> secondHouseRepo ) { _firstHouseRepo = firstHouseRepo; _secondHouseRepo = secondHouseRepo; } // 示例:用第一个仓储添加数据 public async Task AddHouseToFirstDb(HouseEntity house) { await _firstHouseRepo.AddAsync(house); } }
如果是直接从容器解析,也可以用命名解析:
var firstHouseRepo = container.ResolveNamed<IRepository<HouseEntity>>("FirstRepository");
为什么之前的配置会出问题?
- 双连接歧义:你注册了两个同类型的
SQLiteAsyncConnection,Autofac不知道该选哪个,默认只会保留最后一个注册的实例,导致所有仓储都用同一个数据库。 - 抽象类注册错误:
BaseRepository<>是抽象类,Autofac无法实例化它,你的注册本身就是无效的,必须注册具体的实现类(也就是你写的两个SQLiteRepository)。
内容的提问来源于stack exchange,提问作者fandro
相关产品推荐
相关产品推荐

