今天我们主要讲讲如何使用自带IOC容器,虽然自带的功能不是那么强大,但是胜在轻量级..而且..不用引用别的库.
在新的ASP.NET Core中,大量的采用了依赖注入的方式来编写代码.
比如,在我们的Startup类中的ConfigureServices里,就可以看到:
AddMvc AddDbContext 包括我们之前目录游览用到的AddDirectoryBrowser..
都是框架提供好的服务,我们直接注入就可以使用了.
如何注入自己的服务
目前有三种注入,各有不同:
- Transient(瞬时的)
每次请求时都会创建的瞬时生命周期服务。这个生命周期最适合轻量级,无状态的服务。 - Scoped(作用域的)
创建的对象在同一个请求会话时是相同的,每一个不同的会话创建一个不同的实例。 - Singleton(唯一的)
创建的对象在所有的地方所有的请求会话创建的都是不同的。
如何使用这三种生命周期呢?.我们直接在注入的时候用不同的方法就行了,代码如下:
services.AddTransient();
services.AddScoped();
services.AddSingleton();
编写服务
我这里写了一个查询InfluxDb的服务,就用这个作为例子来分析。
- 首先定义接口,IInfluxDbService.cs,接口里面我只写了两个接口。
public interface IInfluxDbService
{
void AddData(string tableName,
Dictionary tags,
Dictionary fields, DateTime timestamp);
IList> 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);
}
///
/// 增加数据
///
/// 表名
/// 索引
/// 字段
/// 时间戳
public async void AddData(string tableName,
Dictionary tags,
Dictionary 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);
}
///
/// 查询数据
///
///
/// 返回查询结果
public IList> 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(a => new InfluxDbService(url, dbName, userName, password));
//以下是系统自动生成
services.AddControllersWithViews();
services.AddMvcCore().AddApiExplorer();
}
只因我这里加入了很多参数,代码就有一大坨了,如果所有服务都这样写,可以想象下,如果服务很多,那么这个方法就会越来越长,后期很难维护,代码看起来也不优雅美观,为了减少ConfigureServices这个函数体的长度,我们可以把这一段封装起来。
封装扩展服务
- 首先新建一个ServiceExtensions的静态类
///
/// 服务扩展类
///
public static class ServiceExtensions
{
///
/// 添加跨域
///
///
public static void ConfigureCors(this IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("AllowAny", builder => builder.SetIsOriginAllowed(isOriginAllowed: _ => true)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
}
///
/// 注入InfluxDb服务
///
///
///
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(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来操作数据库了