我一直在遵循這個教程,以便從我的MVC專案中的類別庫中訪問我的appsettings.json。 geek-tutorial
我在我的類別庫中有一個這樣的類
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類并從另一個類中呼叫方法,例如:
public static class ShortUrlProcessor
{
public static ShortURLModel GetOriginal GetOriginal title">GetOriginalURL(string shortUrl)
{
string sql = $@"SELECT * FROM dbo.shorturl WHERE shortUrl = '{ shortUrl }'"/span>。
var originalURLEnum = SqlDataAccess.LoadData<ShortURLModel>(sql); //<-- 問題
return originalURLEnum.First()。
}
}
但是SqlDataAccess沒有被實體化,為了進行var _sqldataaccess = SqlDataAccess(),我需要傳入一個在該類的建構式中定義的引數。我不知道該傳入什么?我在這個ShortUrlProcessor類中沒有任何IconfigurationManager。我知道這樣做的原因是依賴性注入,但是我還是不明白這一切是如何進行的?
uj5u.com熱心網友回復:
你很接近了,但你需要解決一些問題。SqlDataAccess實作了IConfigManager。為什么?它能提供什么?相反,你應該讓它實作一個介面,使它能夠暴露出其他類所依賴的功能。
public interface ISqlDataAccess
{
List<T> LoadData< T>(string sql) 。
int SaveData< T>(string sql, T data) ;
改變你的SqlDataAccess類來實作這個介面......
public class SqlDataAccess : IsqlDataAccess
當然,還要把它與你的DI容器連接起來。
services.AddTransient<ISqlDataAccess, SqlDataAccess>()。
現在,任何需要運行 SQL 的類都可以依賴 ISqlDataAccess 介面,利用建構式注入來獲得 ISqlDataAccess 的實體。由于我們已經告訴 DI 容器在 ISqlDataAccess 依賴關系出現時提供一個 SqlDataAccess 實體,所以它將在你的應用程式中很好地連接起來。
然后我們遇到了 ShortUrlProcessor 的問題。你將該類宣告為靜態的。這很糟糕,因為這使得它很難使用建構式注入來獲取它的依賴,任何需要呼叫它的方法的其它類都必須直接這樣做,而不是通過一個抽象。這違反了SOLID的依賴反轉原則。由于可維護性和可測驗性,我們應該一直努力撰寫 SOLID 代碼,因此我們需要解決這個問題。
public class ShortUrlProcessor : IShortUrlProcessor
{
readonly ISqlDataAccess _dataAccess。
public ShortUrlProcessor(ISqlDataAccess dataAccess)
{
_dataAccess = dataAccess。
}
public ShortURLModel GetOriginalURL(>string shortUrl) /span>
{
string sql = $@"SELECT * FROM dbo.shorturl WHERE shortUrl = '{ shortUrl }'"。
var originalURLEnum = _dataAccess.LoadData<ShortURLModel>(sql); //<-- problem
return originalURLEnum.First()。
}
}
而且我們需要一個介面,這樣其他的類就不必直接依賴ShortUrlProcessor......
public interface IShortUrlProcessor
{
ShortURLModel GetOriginalURL(string shortUrl) 。
當然,我們需要在我們的DI容器中注冊它。
services.AddTransient<IShortUrlProcessor, ShortUrlProcessor>()。
那么任何需要訪問ShortUrlProcessor功能的類都可以通過抽象的IShortUrlProcessor來實作。你提到你有一個控制器在呼叫這個功能,所以我們也把它連接起來吧。
public class MyController()
{
readonly IShortUrlProcessor _shortUrlProcessor。
public MyController(IShortUrlProcessor shortUrlProcessor)
{
_shortUrlProcessor = shortUrlProcessor。
}
public ActionResult SomeActionMethod() ?
{
var model = _shortUrlProcessor.GetOriginalURL("asdf"/span>)。
return View(model)。
}
}
我們不需要為控制器創建一個介面,因為控制器將被框架呼叫。我們也不必將控制器與DI容器連接起來,因為框架將為我們處理這個問題。
通過這一切,我們可以輕松地隔離測驗各個方法。還有一些需要改進的地方(我在評論中提到的SQL注入攻擊需要修復),但這是朝著正確方向邁出的一步。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/324069.html
標籤:
上一篇:MVC中標簽的HTML渲染
