asp.net Core依賴注入(自帶的IOC容器)


今天我們主要講講如何使用自帶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的服務,就用這個作為例子來分析。

  1. 首先定義接口,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);
}
  1. 編寫服務,繼承自接口,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這個函數體的長度,我們可以把這一段封裝起來。

封裝擴展服務

  1. 首先新建一個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來操作數據庫了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM