我对.NETCore的DI模式还不熟悉,在将连接字符串连接到DAL时遇到了困难。
我按照这个帖子中给出的建议,通过接受的答案和随后的评论。
这是我的基类
public class BaseRepository : IRepository<IDataModel>
{
private readonly IConfiguration config;
public BaseRepository(IConfiguration config)
{
this.config = config;
}
public string GetSQLConnectionString()
{
return config["Data:DefaultConnetion:ConnectionString"];
}
这是继承基类的存储库类的片段
public class PrivacyLevelRepository : BaseRepository, IRepository<PrivacyLevelDM>
{
public PrivacyLevelRepository(IConfiguration config) : base(config) { }
public void Add(PrivacyLevelDM dataModel)
{
...
}
}
这是我的 startup.cs
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
services.AddScoped<IRepository<IDataModel>>(c => new BaseRepository(Configuration));
}
但是,在我的服务层中,repository类的实例化仍然要求将(IConfiguration config)作为参数传递。
PrivacyLevelRepository repo = new PrivacyLevelRepository();
如何将IConfiguration直接加载到我的DAL中,而不必从Controller>BLL>DAL传递它。这看起来效率极低,而且不正确。因为DAL应该确定对象的连接,而不是控制器或服务层。他们应该对数据源不可知,不是吗?
我认为这是一个简单的问题,我只是在DI/IoC范式中没有看到,但是我无法理解。
编辑:我使用的不是实体框架,而是一个自定义的数据层。
谢谢你的帮助。
----------------------------------------------------------------
您可以在配置框架中遵循选项模式。这允许您定义一个自定义类型,该类型保存您的配置设置(静态类型),同时仅限于实际的相关配置。
你可以这样使用它:
public void ConfigureServices(IServiceCollection services)
{
//注册`数据:DefaultConnection`配置节组件
//“DatabaseOptions”类型的配置
services.Configure<DatabaseOptions>(Configuration.GetSection("Data:DefaultConnection"));
//注册数据库存储库
//注意,我们不使用自定义工厂来创建对象
services.AddScoped<IRepository<IDataModel>, BaseRepository>();
}
这假设类型数据库选项如下:
public class DatabaseOptions
{
public string ConnectionString { get; set; }
}
然后,只需将DatabaseOptions注入BaseRepository:
public class BaseRepository
{
private readonly DatabaseOptions _options;
public BaseRepository(IOptions<DatabaseOptions> databaseOptions)
{
_options = databaseOptions.Value;
}
}
当然,如果您有该BaseRepository的子类型,则还需要注册这些子类型并将选项传递给基类:
//同时在“ConfigureServices”方法中注册存储库
services.AddScoped<PrivacyLevelRepository>();
public class PrivacyLevelRepository : BaseRepository, IRepository<PrivacyLevelDM>
{
public PrivacyLevelRepository(IOptions<DatabaseOptions> databaseOptions)
: base(databaseOptions)
{ }
}
我像往常一样实例化和使用回购。我不知道如何使用我没有实例化的类。如何让这个对象知道它依赖于PrivacyLevelRepository?
PrivacyLevelRepository repo = new PrivacyLevelRepository();
returnValue = repo.GetAllByDomainID(DomainID).ToList();
return returnValue;
我像往常一样实例化和使用回购。我不知道如何使用我没有实例化的类。如何让这个对象知道它依赖于PrivacyLevelRepository?
您似乎还不了解依赖注入背后的思想。依赖注入及其基本的控制反转原理简单地说就是避免使用new来创建对象。您不再主动依赖实现(在您的示例中是PrivacyLevelRepository),而是放弃了责任,只依赖外部系统来提供所需的依赖关系。
因此,不是创建新的PrivacyLevelRepository,而是注入由其他地方创建的实例。这会使依赖关系的实现失去耦合。一个非常实际的例子是PrivacyLevelRepository如何依赖IOptions<DatabaseOptions>。作为该存储库的使用者,您不必关心如何获得这样一个对象来创建存储库实例。首先,您甚至不需要知道如何创建存储库实例。
因此,PrivacyLevelRepository的使用者应该遵循与存储库本身相同的思想:存储库不知道如何获取这些数据库选项;它只依赖于构造实体来传递这样一个对象。而你的消费者,我假设一个控制器,也应该这么做:
public class MyController
{
private readonly PrivacyLevelRepository _privacyLevelRepository;
public MyController(PrivacyLevelRepository privacyLevelRepository)
{
// instead of *creating* a repository, we just expect to get one
_privacyLevelRepository = privacyLevelRepository;
}
public IActionResult SomeRoute()
{
var domainId = "whatever";
var data = _privacyLevelRepository.GetAllByDomainID(domainId).ToList();
return View(data);
}
}
当然,在某个时刻,某些东西必须创建依赖关系。但是如果你完全接受依赖注入ASP.NET核心不仅使非常容易,而且积极地要求你这样做,以便完全工作,然后你不需要关心这一部分。您只需在ConfigureServices方法中注册类型,然后期望在需要的地方实现依赖关系。
要了解更多信息,您应该查看文档中的依赖注入一章。