无法从 class 库访问 appsettings.json
Cannot access appsettings.json from class library
我一直在学习本教程,以便从我的 class 库中的 MVC 项目访问我的 appsettings.json。
geek-tutorial
我的 class 库中有一个 class 这样的
using dapper;
public class SqlDataAccess : IConfigManager
{
private readonly IConfiguration _configuration;
public SqlDataAccess(IConfiguration configuration)
{
this._configuration = configuration;
}
public List<T> LoadData<T>(string sql)
{
using (IDbConnection cnn = new SqlConnection(GetConnectionString()))
{
return cnn.Query<T>(sql).ToList();
}
}
public int SaveData<T>(string sql, T data)
{
using (IDbConnection cnn = new SqlConnection(GetConnectionString()))
{
return cnn.Execute(sql, data);
}
}
public string GetConnectionString(string connectionName = "URLShortnerDB")
{
return this._configuration.GetConnectionString(connectionName);
}
}
接口:
public interface IConfigManager
{
string GetConnectionString(string connectionName);
}
我在我的 mvc startup.cs
中添加了 services.AddSingleton<IConfigManager, SqlDataAccess>();
但是现在我想使用我的 SqlDataAccess
class 并调用另一个 class 的方法,例如:
public static class ShortUrlProcessor
{
public static ShortURLModel GetOriginalURL(string shortUrl)
{
string sql = $@"SELECT * FROM dbo.shorturl WHERE shortUrl = '{ shortUrl }'";
var originalURLEnum = SqlDataAccess.LoadData<ShortURLModel>(sql); //<--- problem
return originalURLEnum.First();
}
}
但是 SqlDataAccess
没有被实例化,为了做到 var _sqldataaccess = SqlDataAccess()
我需要传入一个在 class 的构造函数中定义的参数。我不知道要传递什么?我在 ShortUrlProcessor
class 中没有任何 IconfigurationManager。我知道这样做的原因是依赖注入,但是我仍然不明白这一切是如何工作的?
你已经很接近了,但你需要解决一些问题。 SqlDataAccess 实现 IConfigManager。为什么?那提供什么?相反,您应该让它实现一个接口,允许它公开其他 classes 所依赖的功能。
public interface ISqlDataAccess
{
List<T> LoadData<T>(string sql);
int SaveData<T>(string sql, T data);
}
更改您的 SqlDataAccess class 以实现此接口...
public class SqlDataAccess : ISqlDataAccess
当然,将它与您的 DI 容器连接起来。
services.AddTransient<ISqlDataAccess, SqlDataAccess>();
现在,任何需要 运行 SQL 的 class 都可以依赖 ISqlDataAccess 接口,利用构造函数注入来获取 ISqlDataAccess 的实例。由于我们已经告诉 DI 容器在存在 ISqlDataAccess 依赖项时提供 SqlDataAccess 实例,因此它会很好地连接到您的应用程序中。
那么我们遇到了 ShortUrlProcessor 的问题。您声明 class 为静态。这很糟糕,因为它很难使用构造函数注入来获取其依赖项,并且任何其他需要调用其方法的 class 都必须直接这样做,而不是通过抽象。这违反了 SOLID 的依赖倒置原则。由于可维护性和可测试性,我们应该始终努力编写 SOLID 代码,因此我们需要解决这个问题。
public class ShortUrlProcessor : IShortUrlProcessor
{
readonly ISqlDataAccess _dataAccess;
public ShortUrlProcessor(ISqlDataAccess dataAccess)
{
_dataAccess = dataAccess;
}
public ShortURLModel GetOriginalURL(string shortUrl)
{
string sql = $@"SELECT * FROM dbo.shorturl WHERE shortUrl = '{ shortUrl }'";
var originalURLEnum = _dataAccess.LoadData<ShortURLModel>(sql); //<--- problem
return originalURLEnum.First();
}
}
我们需要一个接口,这样其他 classes 就不必直接依赖于 ShortUrlProcessor...
public interface IShortUrlProcessor
{
ShortURLModel GetOriginalURL(string shortUrl);
}
当然,我们需要将其注册到我们的 DI 容器中。
services.AddTransient<IShortUrlProcessor, ShortUrlProcessor>();
然后任何需要访问 ShortUrlProcessor 功能的 class 都可以通过抽象 IShortUrlProcessor 来实现。你提到你有一个控制器调用它,所以我们也把它连接起来。
public class MyController()
{
readonly IShortUrlProcessor _shortUrlProcessor;
public MyController(IShortUrlProcessor shortUrlProcessor)
{
_shortUrlProcessor = shortUrlProcessor;
}
public ActionResult SomeActionMethod()
{
var model = _shortUrlProcessor.GetOriginalURL("asdf");
return View(model);
}
}
我们不必为控制器创建接口,因为控制器会被框架调用。而且我们不必将控制器与 DI 容器连接起来,因为框架会为我们处理。
通过执行所有这些操作,我们可以轻松地单独测试各个方法。还有一些需要改进的地方(我在评论中提到的 SQL 注入攻击需要修复),但这是朝着正确方向迈出的良好一步。
我一直在学习本教程,以便从我的 class 库中的 MVC 项目访问我的 appsettings.json。 geek-tutorial
我的 class 库中有一个 class 这样的
using dapper;
public class SqlDataAccess : IConfigManager
{
private readonly IConfiguration _configuration;
public SqlDataAccess(IConfiguration configuration)
{
this._configuration = configuration;
}
public List<T> LoadData<T>(string sql)
{
using (IDbConnection cnn = new SqlConnection(GetConnectionString()))
{
return cnn.Query<T>(sql).ToList();
}
}
public int SaveData<T>(string sql, T data)
{
using (IDbConnection cnn = new SqlConnection(GetConnectionString()))
{
return cnn.Execute(sql, data);
}
}
public string GetConnectionString(string connectionName = "URLShortnerDB")
{
return this._configuration.GetConnectionString(connectionName);
}
}
接口:
public interface IConfigManager
{
string GetConnectionString(string connectionName);
}
我在我的 mvc startup.cs
中添加了services.AddSingleton<IConfigManager, SqlDataAccess>();
但是现在我想使用我的 SqlDataAccess
class 并调用另一个 class 的方法,例如:
public static class ShortUrlProcessor
{
public static ShortURLModel GetOriginalURL(string shortUrl)
{
string sql = $@"SELECT * FROM dbo.shorturl WHERE shortUrl = '{ shortUrl }'";
var originalURLEnum = SqlDataAccess.LoadData<ShortURLModel>(sql); //<--- problem
return originalURLEnum.First();
}
}
但是 SqlDataAccess
没有被实例化,为了做到 var _sqldataaccess = SqlDataAccess()
我需要传入一个在 class 的构造函数中定义的参数。我不知道要传递什么?我在 ShortUrlProcessor
class 中没有任何 IconfigurationManager。我知道这样做的原因是依赖注入,但是我仍然不明白这一切是如何工作的?
你已经很接近了,但你需要解决一些问题。 SqlDataAccess 实现 IConfigManager。为什么?那提供什么?相反,您应该让它实现一个接口,允许它公开其他 classes 所依赖的功能。
public interface ISqlDataAccess
{
List<T> LoadData<T>(string sql);
int SaveData<T>(string sql, T data);
}
更改您的 SqlDataAccess class 以实现此接口...
public class SqlDataAccess : ISqlDataAccess
当然,将它与您的 DI 容器连接起来。
services.AddTransient<ISqlDataAccess, SqlDataAccess>();
现在,任何需要 运行 SQL 的 class 都可以依赖 ISqlDataAccess 接口,利用构造函数注入来获取 ISqlDataAccess 的实例。由于我们已经告诉 DI 容器在存在 ISqlDataAccess 依赖项时提供 SqlDataAccess 实例,因此它会很好地连接到您的应用程序中。
那么我们遇到了 ShortUrlProcessor 的问题。您声明 class 为静态。这很糟糕,因为它很难使用构造函数注入来获取其依赖项,并且任何其他需要调用其方法的 class 都必须直接这样做,而不是通过抽象。这违反了 SOLID 的依赖倒置原则。由于可维护性和可测试性,我们应该始终努力编写 SOLID 代码,因此我们需要解决这个问题。
public class ShortUrlProcessor : IShortUrlProcessor
{
readonly ISqlDataAccess _dataAccess;
public ShortUrlProcessor(ISqlDataAccess dataAccess)
{
_dataAccess = dataAccess;
}
public ShortURLModel GetOriginalURL(string shortUrl)
{
string sql = $@"SELECT * FROM dbo.shorturl WHERE shortUrl = '{ shortUrl }'";
var originalURLEnum = _dataAccess.LoadData<ShortURLModel>(sql); //<--- problem
return originalURLEnum.First();
}
}
我们需要一个接口,这样其他 classes 就不必直接依赖于 ShortUrlProcessor...
public interface IShortUrlProcessor
{
ShortURLModel GetOriginalURL(string shortUrl);
}
当然,我们需要将其注册到我们的 DI 容器中。
services.AddTransient<IShortUrlProcessor, ShortUrlProcessor>();
然后任何需要访问 ShortUrlProcessor 功能的 class 都可以通过抽象 IShortUrlProcessor 来实现。你提到你有一个控制器调用它,所以我们也把它连接起来。
public class MyController()
{
readonly IShortUrlProcessor _shortUrlProcessor;
public MyController(IShortUrlProcessor shortUrlProcessor)
{
_shortUrlProcessor = shortUrlProcessor;
}
public ActionResult SomeActionMethod()
{
var model = _shortUrlProcessor.GetOriginalURL("asdf");
return View(model);
}
}
我们不必为控制器创建接口,因为控制器会被框架调用。而且我们不必将控制器与 DI 容器连接起来,因为框架会为我们处理。
通过执行所有这些操作,我们可以轻松地单独测试各个方法。还有一些需要改进的地方(我在评论中提到的 SQL 注入攻击需要修复),但这是朝着正确方向迈出的良好一步。