今天我們主要講講如何使用自帶IOC容器,雖然自帶的功能不是那么強大,但是勝在輕量級..而且..不用引用別的庫.
在新的ASP.NET Core中,大量的采用了依賴注入的方式來編寫代碼.
比如,在我們的Startup類中的ConfigureServices里,就可以看到:
AddMvc AddDbContext 包括我們之前目錄游覽用到的AddDirectoryBrowser..
都是框架提供好的服務,我們直接注入就可以使用了.
如何注入自己的服務
目前有三種注入,各有不同:
- Transient(瞬時的)
每次請求時都會創建的瞬時生命周期服務。這個生命周期最適合輕量級,無狀態的服務。 - Scoped(作用域的)
創建的對象在同一個請求會話時是相同的,每一個不同的會話創建一個不同的實例。 - Singleton(唯一的)
創建的對象在所有的地方所有的請求會話創建的都是不同的。
如何使用這三種生命周期呢?.我們直接在注入的時候用不同的方法就行了,代碼如下:
services.AddTransient<ITestService, TestService>();
services.AddScoped<ITestService, TestService>();
services.AddSingleton<ITestService, TestService>();
編寫服務
我這里寫了一個查詢InfluxDb的服務,就用這個作為例子來分析。
- 首先定義接口,IInfluxDbService.cs,接口里面我只寫了兩個接口。
public interface IInfluxDbService
{
void AddData(string tableName,
Dictionary<string, object> tags,
Dictionary<string, object> fields, DateTime timestamp);
IList<IList<object>> GetData(string queries);
}
- 編寫服務,繼承自接口,InfluxDbService.cs
可以看到帶了一個含參構造函數,傳入數據庫地址及用戶密碼等必須信息。
public class InfluxDbService:IInfluxDbService
{
//聲明InfluxDbClient
private InfluxDbClient clientDb;
private string dbName;
public InfluxDbService(string infuxUrl, string dbName,string infuxUser, string infuxPwd)
{
this.dbName = dbName;
clientDb = new InfluxDbClient(infuxUrl, infuxUser, infuxPwd, InfluxDbVersion.Latest);
}
/// <summary>
/// 增加數據
/// </summary>
/// <param name="tableName">表名</param>
/// <param name="tags">索引</param>
/// <param name="fields">字段</param>
/// <param name="timestamp">時間戳</param>
public async void AddData(string tableName,
Dictionary<string,object> tags,
Dictionary<string,object> fields,DateTime timestamp)
{
//基於InfluxData.Net.InfluxDb.Models.Point實體准備數據
var pointModel = new Point();
pointModel.Name = tableName;
pointModel.Tags = tags;
pointModel.Fields = fields;
pointModel.Timestamp = timestamp;
//從指定庫中寫入數據,支持傳入多個對象的集合
var response = await clientDb.Client.WriteAsync(pointModel, this.dbName);
}
/// <summary>
/// 查詢數據
/// </summary>
/// <param name="queries"></param>
/// <returns>返回查詢結果</returns>
public IList<IList<object>> GetData(string queries)
{
//從指定庫中查詢數據
var response = clientDb.Client.QueryAsync(queries, this.dbName);
//得到Serie集合對象(返回執行多個查詢的結果)
var series = response.Result.ToList();
var list = series[0].Values;
return list;
}
}
這樣我們的服務就寫完了,接下來就是如何注入服務。
依賴注入
我們可以在Startup類中直接注入,比如,我這里就拿AddSingleton作為示例進行演示。
public void ConfigureServices(IServiceCollection services)
{
//讀配置文件獲取參數
var url = configuration.GetValue("InfluxDb:ConnectionString", "http://127.0.0.1:8086");
var dbName = configuration.GetValue("InfluxDb:DatabaseName", "autocontrol");
var userName = configuration.GetValue("InfluxDb:UserName", "admin");
var password = configuration.GetValue("InfluxDb:Password", "admin");
//注入依賴
services.AddSingleton<IInfluxDbService, InfluxDbService>(a => new InfluxDbService(url, dbName, userName, password));
//以下是系統自動生成
services.AddControllersWithViews();
services.AddMvcCore().AddApiExplorer();
}
只因我這里加入了很多參數,代碼就有一大坨了,如果所有服務都這樣寫,可以想象下,如果服務很多,那么這個方法就會越來越長,后期很難維護,代碼看起來也不優雅美觀,為了減少ConfigureServices這個函數體的長度,我們可以把這一段封裝起來。
封裝擴展服務
- 首先新建一個ServiceExtensions的靜態類
/// <summary>
/// 服務擴展類
/// </summary>
public static class ServiceExtensions
{
/// <summary>
/// 添加跨域
/// </summary>
/// <param name="services"></param>
public static void ConfigureCors(this IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("AllowAny", builder => builder.SetIsOriginAllowed(isOriginAllowed: _ => true)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
}
/// <summary>
/// 注入InfluxDb服務
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
public static void AddInfluxDbService(this IServiceCollection services, IConfiguration configuration)
{
//服務DI注入
var url = configuration.GetValue("InfluxDb:ConnectionString", "http://127.0.0.1:8086");
var dbName = configuration.GetValue("InfluxDb:DatabaseName", "autocontrol");
var userName = configuration.GetValue("InfluxDb:UserName", "admin");
var password = configuration.GetValue("InfluxDb:Password", "admin");
services.AddSingleton<IInfluxDbService, InfluxDbService>(a => new InfluxDbService(url, dbName, userName, password));
}
}
我這里封裝了兩個服務。
- ConfigureCors:跨域的服務
- AddInfluxDbService:InfluxDb的服務
public void ConfigureServices(IServiceCollection services)
{
//設置跨域處理
services.ConfigureCors();
//注入服務
services.AddInfluxDbService(Configuration);
services.AddControllersWithViews();
services.AddMvcCore().AddApiExplorer();
}
這樣就相當簡潔了,哈哈
控制器
修改控制器代碼如下
private IInfluxDbService _influxDbService;
public CurrentStatusController(IInfluxDbService influxDbService)
{
_influxDbService = influxDbService;
}
這樣就控制器就可以使用_influxDbService來操作數據庫了