如何避免在表示层中直接引用数据访问层?
如何避免表示层直接引用数据层
你的问题核心在于数据层定义的IConnectionProvider接口迫使表示层必须引用数据层,打破了Data Layer -> View Model -> Presentation Layer的依赖方向。下面是两种干净的解决方案,完全不需要在表示层引用数据层:
方案一:将抽象接口移到共享核心层(推荐)
这是最符合依赖倒置原则的做法,把所有跨层的抽象定义放到一个独立的核心/契约层,让所有层都依赖这个核心层,而不是互相依赖。
具体步骤:
创建共享核心项目
新建一个类库项目(比如命名为MyApp.Core或MyApp.Contracts),把IConnectionProvider接口移到这里:namespace MyApp.Core; public interface IConnectionProvider { string DbPath { get; } }修改数据层依赖
让你的数据层项目引用这个核心层,更新SQLiteDb的代码,依赖核心层的接口:using MyApp.Core; public class SQLiteDb : DbContext, IDbContext { internal const string DefaultDatabaseName = "My.db"; private readonly string connectionString; public SQLiteDb(IConnectionProvider connectionProvider) { connectionString = connectionProvider.DbPath; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite(connectionString); } }表示层实现核心层接口
表示层项目只需要引用核心层,实现核心层的IConnectionProvider,完全不用碰数据层:using MyApp.Core; public class SqlConnectionProvider : IConnectionProvider { private string dbPath = string.Empty; public string DbPath { get { if (string.IsNullOrEmpty(dbPath)) { dbPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "MyDb.sqlite"); } return dbPath; } } }依赖注入注册
在你的项目启动入口(比如MAUI的MauiProgram.cs、WPF的App.xaml.cs)注册这个实现,让DI容器把它注入到数据层:builder.Services.AddSingleton<IConnectionProvider, SqlConnectionProvider>(); builder.Services.AddScoped<IDbContext, SQLiteDb>();
方案二:在ViewModel层定义接口(小型项目可选)
如果不想新增核心项目,也可以把IConnectionProvider定义在ViewModel层:
- ViewModel层定义
IConnectionProvider接口 - 数据层引用ViewModel层,依赖这个接口
- 表示层引用ViewModel层,实现接口
这种方式虽然不用新增项目,但会让数据层依赖ViewModel层(上层),不符合严格的依赖倒置原则,适合小型项目快速解决问题。
为什么不推荐ViewModel包装类?
你提到的ViewModel包装类确实会增加额外的依赖和冗余代码——相当于在ViewModel层再套一层抽象,反而让架构更复杂,不如直接把抽象提到共享层或ViewModel层来得简洁。
内容的提问来源于stack exchange,提问作者Dishant
相关产品推荐
相关产品推荐

