using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
//services.AddTransient<IFly, Pig>();
//services.AddSingleton<IFly, Pig>();
services.AddScoped<IFly, Pig>();
services.AddLogging(options =>
{
options.AddConsole().SetMinimumLevel(LogLevel.Debug);
});
var provider = services.BuildServiceProvider();
//验证scope生命周期
var scope1 = provider.CreateScope();
var service = scope1.ServiceProvider.GetService<IFly>();
//var service = provider.GetService<IFly>();
var scope2 = provider.CreateScope();
var service2 = scope2.ServiceProvider.GetServices<IFly>();
//var service2 = provider.GetService<IFly>();
var logService = provider.GetService<ILoggerFactory>();
service.Fly();
Console.Read();
}
}
public interface IFly
{
void Fly();
}
public class Pig : IFly
{
ILogger<Pig> logger = null;
public Pig(ILoggerFactory loggerFactory)
{
Console.WriteLine("构造函数被调用");
logger= loggerFactory.CreateLogger<Pig>();
}
public void Fly()
{
logger.LogDebug("这是Console的日志");
Console.WriteLine("风口来了,猪都可以飞起来");
}
}
}
.net core系列之《.net core
内置IOC容器ServiceCollection
》
一、IOC介绍
IOC:全名(Inversion of Control
)-控制反转
IOC意味着我们将对象的创建控制权交给了外部容器,我们不管它是如何创建的,我们只需要知道,当我们想要某个实例时,我们可以直接从这个外部容器中去拿,而再也不需要我们去new了,充分体现了DIP(依赖倒置原则),也体现了我们经常挂在嘴边的面向接口编程。
DI:全名(Dependency Injection
)-依赖注入
DI意味着将类型之间的依赖关系注入到DI容器中
在之前的.Net Framework
中并没有集成IOC
,虽然Microsoft自己有一套"Unity",想要使用IOC+DI时,还需要我们自己去安装包,进行三部曲等等各种操作
比较流行的IOC容器技术:Autofac、Unity、NInject。。。
二、.net core
内置IOC容器(ServiceCollection
)
1、打开NuGet包管理器,安装 Microsoft.Extensions.DependencyInjection
包
2、实现代码如下:
public interface ISqlHelper
{
void GetAll();
}
public class SqlServerHelper : ISqlHelper
{
public void GetAll()
{
Console.WriteLine("this is "+typeof(SqlServerHelper));
}
}
static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
services.AddTransient<ISqlHelper, SqlServerHelper>();
var provider=services.BuildServiceProvider();
var sqlHelper=provider.GetService<ISqlHelper>();
sqlHelper.GetAll();
Console.ReadKey();
}
运行结果如下:
当我们在执行业务逻辑时想要写入一些日志(Log
),必然会当然依赖这个类,那么会形成了SqlHelper
类与Log
类之前的依赖关系,我们可以将之前的依赖关系转移到DI
容器中,也就是依赖注入(DI
),然后在DI
容器获取服务(对象)
示例代码如下:
public interface ILog
{
void LogInfo(string msg);
}
public class Log : ILog
{
public void LogInfo(string msg)
{
Console.WriteLine(msg);
}
}
static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
services.AddTransient<ILog, Log>();
services.AddTransient<ISqlHelper, SqlServerHelper>();
var provider=services.BuildServiceProvider();
var sqlHelper= provider.GetService<ISqlHelper>();
sqlHelper.GetAll();
Console.ReadKey();
}
如果如下:
三、组件的生命周期
1、Singleton
:单例,全局唯一实例
2、Scoped
:作用域,在一个作用域中唯一实例,比如在Asp.Net Core
应用程序中一次请求相当于一个Scoped
3、Transient
:瞬时,每次的实例都是一个新的对象
Transient:
static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
services.AddTransient<ISqlHelper, SqlServerHelper>();
var provider=services.BuildServiceProvider();
var sqlHelper=provider.GetService<ISqlHelper>();
sqlHelper= provider.GetService<ISqlHelper>();
Console.ReadKey();
}
结果如下:
Singleton:
static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
services.AddSingleton<ISqlHelper, SqlServerHelper>();
var provider=services.BuildServiceProvider();
var sqlHelper=provider.GetService<ISqlHelper>();
sqlHelper= provider.GetService<ISqlHelper>();
Console.ReadKey();
}
结果如下:
Scoped:
1、一个作用域下:
static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
services.AddScoped<ISqlHelper, SqlServerHelper>();
var provider=services.BuildServiceProvider();
var sqlHelper=provider.GetService<ISqlHelper>();
sqlHelper= provider.GetService<ISqlHelper>();
Console.ReadKey();
}
结果如下:
2、二个作用域下:
static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
services.AddScoped<ISqlHelper, SqlServerHelper>();
var provider=services.BuildServiceProvider();
var scope1=provider.CreateScope();//在一个作用域下创建第一个子作用域
var scope2= provider.CreateScope();//在一个作用域下创建第二个子作用域
var sqlHelper= scope1.ServiceProvider.GetService<ISqlHelper>();
sqlHelper= scope2.ServiceProvider.GetService<ISqlHelper>();
Console.ReadKey();
}
如果如下:
注意:由于是控制台项目,只能用子作用域来体现作用域的特点,在web项目中,一次请求就相当于一个作用域