文章目录
- 前言
- KeyedService
- Key缺少
- Key值覆盖
- KeyedService.AnyKey
- 生命周期
- 测试代码
- 总结
前言
我之前写过一篇Ioc容器的使用,用的是微软的IOC容器。这次我们再去深入了解一下IOC 和控制反转
.NET Core 依赖注入 Microsoft.Extensions.DependencyInjection
ASP.NET CORE 内置的IOC解读及使用
ServiceCollection IOC容器 服务的生命周期
Dependency Injection 8.0新功能——KeyedService
作者: 寻己Tenleft
出处:https://www.cnblogs.com/tenleft/p/17719609.html
本站使用「CC BY 4.0」创作共享协议,转载请在文章明显位置注明作者及出处。
详解.NET依赖注入中对象的创建与“销毁”
KeyedService
使用Key值来对类进行区分。
Dependency Injection 8.0新功能——KeyedService
public class Person
{
public List<Phone> Phones { get; set; }
public Person() {
}
/// <summary>
/// 使用拿到对应的
/// </summary>
/// <param name="phone1"></param>
/// <param name="phone2"></param>
public Person( [FromKeyedServices("A")] Phone phone1, [FromKeyedServices("B")] Phone phone2)
{
Phones = new List<Phone>
{
phone1,
phone2
};
}
}
public class Phone
{
public string Name { get; set; }
public Phone() { }
}
static void Main(string[] args)
{
IServiceCollection services = new ServiceCollection()
.AddSingleton<Person>()
.AddKeyedScoped<Phone>("A")
.AddKeyedScoped<Phone>("B");
var builder = services.BuildServiceProvider();
builder.GetKeyedService<Phone>("A").Name = "大米";
builder.GetKeyedService<Phone>("B").Name = "小花";
var person = builder.GetService<Person>();
Console.WriteLine(JsonConvert.SerializeObject(person));
Console.WriteLine("运行完成!");
Console.ReadKey();
}
也可以这么写
static void Main(string[] args)
{
IServiceCollection services = new ServiceCollection()
.AddSingleton<NetCore.Models.Person>()
.AddKeyedScoped<Phone>("A", (sp,key) =>
{
return new Phone() {Name = "小花" };
})
.AddKeyedScoped<Phone>("B", (sp, key) =>
{
return new Phone() { Name = "大米" };
});
var builder = services.BuildServiceProvider();
var person = builder.GetService<NetCore.Models.Person>();
Console.WriteLine(JsonConvert.SerializeObject(person));
Console.WriteLine("运行完成!");
Console.ReadKey();
}
Key缺少
如果Key的构造函数对应不上,就会出现问题
Key值覆盖
KeyedService.AnyKey
因为之前的KeyService的要求是必须声明,才能注入,如果缺一个就直接不走构造函数了,实在是太严格了。
使用KeyedService.AnyKey就是尽可能的获取对应的Key的服务
static void Main(string[] args)
{
IServiceCollection services = new ServiceCollection()
.AddSingleton<NetCore.Models.Person>()
.AddKeyedScoped<Phone>(KeyedService.AnyKey);
var builder = services.BuildServiceProvider();
//builder.GetServices<Phone>();
var res = builder.GetKeyedService<Phone>("A");
Console.WriteLine(res.Name);
var person = builder.GetService<NetCore.Models.Person>();
Console.WriteLine(JsonConvert.SerializeObject(person));
Console.WriteLine("运行完成!");
Console.ReadKey();
}
public class Phone
{
public string Name { get; set; }
public Phone() { }
/// <summary>
/// 尝试去拿Key的值
/// </summary>
/// <param name="key"></param>
public Phone([ServiceKey] string key )
{
Console.WriteLine($"我拿到Key了{key}");
}
}
生命周期
详情可以看这篇文章,写的是真的厉害
详解.NET依赖注入中对象的创建与“销毁”
测试代码
- this.GetHashCode()会返回每个新对象唯一的code,来区分对象
- 继承IDisposable后,IOC容器会在合适的地方自动调用Dispose方法
public class SingleService : IDisposable
{
public string Name { get; set; }
public SingleService([ServiceKey] string key)
{
Name = key;
Console.WriteLine($"我被创造了[{Name}]-{this.GetHashCode()}");
}
public void Dispose()
{
Console.WriteLine($"我被销毁了[{Name}]-{this.GetHashCode()}");
}
}
public class ScopedService : IDisposable
{
public string Name { get; set; }
public ScopedService()
{
Console.WriteLine($"我被创造了[{Name}]-{this.GetHashCode()}");
}
public ScopedService([ServiceKey] string key)
{
Name = key;
Console.WriteLine($"我被创造了[{Name}]-{this.GetHashCode()}");
}
public void Dispose()
{
Console.WriteLine($"我被销毁了[{Name}]-{this.GetHashCode()}");
}
}
public class TransientService : IDisposable
{
public string Name { get; set; }
public TransientService([ServiceKey] string key)
{
Name = key;
Console.WriteLine($"我被创造了[{Name}]-{this.GetHashCode()}");
}
public void Dispose()
{
Console.WriteLine($"我被销毁了[{Name}]-{this.GetHashCode()}");
}
}
static void Main(string[] args)
{
var services = new ServiceCollection()
.AddKeyedSingleton<SingleService>(KeyedService.AnyKey)
.AddKeyedScoped<ScopedService>(KeyedService.AnyKey)
.AddKeyedTransient<TransientService>(KeyedService.AnyKey).BuildServiceProvider();
Console.WriteLine();
services.GetKeyedService<SingleService>("A");
services.GetKeyedService<ScopedService>("B");
services.GetKeyedService<TransientService>("C");
Console.WriteLine();
services.GetKeyedService<SingleService>("A");
services.GetKeyedService<ScopedService>("B");
services.GetKeyedService<TransientService>("C");
//测试Scoped
using (var scope = services.CreateScope())
{
Console.WriteLine("");
scope.ServiceProvider.GetKeyedService<SingleService>("A");
scope.ServiceProvider.GetKeyedService<ScopedService>("B");
scope.ServiceProvider.GetKeyedService<TransientService>("C");
}
Console.WriteLine();
Console.WriteLine("运行完成!");
Console.ReadKey();
}
总结
这次算是补上了上次的坑,彻底弄懂了IOC 容器的生命周期。怎么玩我还不了解,懂了至少吹牛逼的时候有谈资。