解析 .Net Core 注入——注册服务

|
interface ITransient { }
class Transient : ITransient { }
interface ISingleton { }
class Singleton : ISingleton { }
interface IScoped { }
class Scoped : IScoped { }
class Program
{
static void Main(string[] args)
{
IServiceCollection services = new ServiceCollection();
services = services.AddTransient<ITransient, Transient>();
services = services.AddScoped<IScoped, Scoped>();
services = services.AddSingleton<ISingleton, Singleton>();
IServiceProvider serviceProvider = services.BuildServiceProvider();
Console.WriteLine(ReferenceEquals(serviceProvider.GetService<ITransient>(), serviceProvider.GetService<ITransient>()));
Console.WriteLine(ReferenceEquals(serviceProvider.GetService<IScoped>(), serviceProvider.GetService<IScoped>()));
Console.WriteLine(ReferenceEquals(serviceProvider.GetService<ISingleton>(), serviceProvider.GetService<ISingleton>()));
IServiceProvider serviceProvider1 = serviceProvider.CreateScope().ServiceProvider;
IServiceProvider serviceProvider2 = serviceProvider.CreateScope().ServiceProvider;
Console.WriteLine(ReferenceEquals(serviceProvider1.GetService<IScoped>(), serviceProvider1.GetService<IScoped>()));
Console.WriteLine(ReferenceEquals(serviceProvider1.GetService<IScoped>(), serviceProvider2.GetService<IScoped>()));
Console.WriteLine(ReferenceEquals(serviceProvider1.GetService<ISingleton>(), serviceProvider2.GetService<ISingleton>()));
/* False
* True
* True
* True
* False
* True
*/
}
}
|
|
public interface IServiceCollection : IList<ServiceDescriptor>
{
}
|
|
public class ServiceDescriptor
{
public ServiceLifetime Lifetime { get; }
public Type ServiceType { get; }
public Type ImplementationType { get; }
public object ImplementationInstance { get; }
public Func<IServiceProvider, object> ImplementationFactory { get; }
}
|
|
public static IServiceCollection AddTransient<TService, TImplementation>(this IServiceCollection services)
where TService : class
where TImplementation : class, TService
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
return services.AddTransient(typeof(TService), typeof(TImplementation));
}
|
|
public enum ServiceLifetime
{
Singleton,
Scoped,
Transient
}
|
|
public class MyServiceProvider : IServiceProvider
{
private List<ServiceDescriptor> serviceDescriptors = new List<ServiceDescriptor>();
private Dictionary<Type, object> SingletonServices = new Dictionary<Type, object>();
public MyServiceProvider(IEnumerable<ServiceDescriptor> serviceDescriptors)
{
this.serviceDescriptors.AddRange(serviceDescriptors);
}
public object GetService(Type serviceType)
{
var descriptor = serviceDescriptors.FirstOrDefault(t => t.ServiceType == serviceType);
if(descriptor == null)
{
throw new Exception($"服务‘{serviceType.Name}’未注册");
}
else
{
switch (descriptor.Lifetime)
{
case ServiceLifetime.Singleton:
if (SingletonServices.TryGetValue(descriptor.ServiceType,out var obj))
{
return obj;
}
else
{
var singletonObject = Activator.CreateInstance(descriptor.ImplementationType);
SingletonServices.Add(descriptor.ServiceType, singletonObject);
return singletonObject;
}
case ServiceLifetime.Scoped:
throw new NotSupportedException($"创建失败,暂时不支持 Scoped");
case ServiceLifetime.Transient:
var transientObject = Activator.CreateInstance(descriptor.ImplementationType);
return transientObject;
default:
throw new NotSupportedException("创建失败,不能识别的 LifeTime");
}
}
}
}
public static class ServiceCollectionContainerBuilderExtensions
{public static MyServiceProvider BuildeMyServiceProvider(this IServiceCollection services)
{
return new MyServiceProvider(services);
}
}
|
|
case ServiceLifetime.Singleton:
if (SingletonServices.TryGetValue(descriptor.ServiceType,out var obj))
{
return obj;
}
else
{
if(descriptor.ImplementationType != null)
{
var singletonObject = Activator.CreateInstance(descriptor.ImplementationType);
SingletonServices.Add(descriptor.ServiceType, singletonObject);
return singletonObject;
}
else if(descriptor.ImplementationInstance != null)
{
SingletonServices.Add(descriptor.ServiceType, descriptor.ImplementationInstance);
return descriptor.ImplementationInstance;
}
else if(descriptor.ImplementationFactory != null)
{
var singletonObject = descriptor.ImplementationFactory.Invoke(this);
SingletonServices.Add(descriptor.ServiceType, singletonObject);
return singletonObject;
}
else
{
throw new Exception("创建服务失败,无法找到实例类型或实例");
}
}
|
|
public sealed class ServiceProvider : IServiceProvider, IDisposable, IServiceProviderEngineCallback
{
private readonly IServiceProviderEngine _engine;
internal ServiceProvider(IEnumerable<ServiceDescriptor> serviceDescriptors, ServiceProviderOptions options)
{
//此处省略了一些代码
switch (options.Mode)
{
case ServiceProviderMode.Dynamic:
_engine = new DynamicServiceProviderEngine(serviceDescriptors, callback);
break;
//此处省略了一些代码
default:
throw new ArgumentOutOfRangeException(nameof(options.Mode));
}
}
public object GetService(Type serviceType) => _engine.GetService(serviceType);
public void Dispose() => _engine.Dispose();
}
|
|
internal abstract class ServiceProviderEngine : IServiceProviderEngine, IServiceScopeFactory
{
internal CallSiteFactory CallSiteFactory { get; }
protected ServiceProviderEngine(IEnumerable<ServiceDescriptor> serviceDescriptors, IServiceProviderEngineCallback callback)
{
//省略了一些代码
CallSiteFactory = new CallSiteFactory(serviceDescriptors);
CallSiteFactory.Add(typeof(IServiceProvider), new ServiceProviderCallSite());
CallSiteFactory.Add(typeof(IServiceScopeFactory), new ServiceScopeFactoryCallSite());
}
}
|
|
internal class CallSiteFactory
{
private readonly List<ServiceDescriptor> _descriptors;
private readonly Dictionary<Type, IServiceCallSite> _callSiteCache = new Dictionary<Type, IServiceCallSite>();
private readonly Dictionary<Type, ServiceDescriptorCacheItem> _descriptorLookup = new Dictionary<Type, ServiceDescriptorCacheItem>();
private struct ServiceDescriptorCacheItem
{
private ServiceDescriptor _item;
private List<ServiceDescriptor> _items;
//省略了一些代码
}
}
internal interface IServiceCallSite
{
Type ServiceType { get; }
Type ImplementationType { get; }
}
|
|
public void Add(Type type, IServiceCallSite serviceCallSite)
{
_callSiteCache[type] = serviceCallSite;
}
|
|
internal class ServiceProviderCallSite : IServiceCallSite
{
public Type ServiceType { get; } = typeof(IServiceProvider);
public Type ImplementationType { get; } = typeof(ServiceProvider);
}
internal class ServiceScopeFactoryCallSite : IServiceCallSite
{
public Type ServiceType { get; } = typeof(IServiceScopeFactory);
public Type ImplementationType { get; } = typeof(ServiceProviderEngine);
}
|
|
static void Main(string[] args)
{
IServiceCollection services = new ServiceCollection();
var serviceProvider = services.BuildServiceProvider();
Console.WriteLine(ReferenceEquals(serviceProvider.GetService<IServiceProvider>(), serviceProvider.GetService<IServiceProvider>()));
var serviceProvider1 = serviceProvider.CreateScope().ServiceProvider;
var serviceProvider2 = serviceProvider.CreateScope().ServiceProvider;
Console.WriteLine(ReferenceEquals(serviceProvider1.GetService<IServiceProvider>(), serviceProvider2.GetService<IServiceProvider>()));
var serviceProvider3 = serviceProvider.GetService<IServiceProvider>();
var serviceProvider4 = serviceProvider.GetService<IServiceProvider>();
var serviceProvider3_1 = serviceProvider3.GetService<IServiceProvider>();
var serviceProvider4_1 = serviceProvider4.GetService<IServiceProvider>();
Console.WriteLine(ReferenceEquals(serviceProvider3,serviceProvider4));
Console.WriteLine(ReferenceEquals(serviceProvider3_1, serviceProvider4_1));
Console.WriteLine(ReferenceEquals(serviceProvider3, serviceProvider3_1));
Console.WriteLine(ReferenceEquals(serviceProvider3,serviceProvider));
/* True
* False
* True
* True
* True
* False
*/
}
|
解析 .Net Core 注入——注册服务的更多相关文章
- 解析 .Net Core 注入 (1) 注册服务
在学习 Asp.Net Core 的过程中,注入可以说是无处不在,对于 .Net Core 来说,它是独立的一个程序集,没有复杂的依赖项和配置文件,所以对于学习 Asp.Net Core 源码的朋友来 ...
- 解析 .Net Core 注入 (3) 创建对象
回顾 通过前两节的学习,我们知道 IServiceCollection 以元数据(ServiceDescriptor)的形式存放着用户注册的服务,它的 IServiceCollection 的拓展方法 ...
- 解析 .Net Core 注入 (2) 创建容器
在上一节的学习中,我们已经知道了通过 IServiceCollection 拓展方法创建 IServiceProvider 默认的是一个类型为 ServiceProvider 对象,并且实际提供创建对 ...
- .Net Core 注入学习——注册服务
解析 .Net Core 注入——注册服务发表于:2017-10-23 10:47 作者:行走即歌 来源:51Testing软件测试网采编字体:大 中 小 | 上一篇 | 下一篇 |我要投稿 | 推荐 ...
- 依赖注入[7]: .NET Core DI框架[服务注册]
包含服务注册信息的IServiceCollection对象最终被用来创建作为DI容器的IServiceProvider对象.服务注册就是创建出现相应的ServiceDescriptor对象并将其添加到 ...
- .NET CORE学习笔记系列(2)——依赖注入[7]: .NET Core DI框架[服务注册]
原文https://www.cnblogs.com/artech/p/net-core-di-07.html 包含服务注册信息的IServiceCollection对象最终被用来创建作为DI容器的IS ...
- 自动注册服务NET Core扩展IServiceCollection
NET Core扩展IServiceCollection自动注册服务 前言 在ASP.NET Core中使用依赖注入中使用很简单,只需在Startup类的ConfigureServices()方法中, ...
- 依赖注入[8]: .NET Core DI框架[服务消费]
包含服务注册信息的IServiceCollection对象最终被用来创建作为DI容器的IServiceProvider对象.当需要消费某个服务实例的时候,我们只需要指定服务类型调用IServicePr ...
- Asp.net core 向Consul 注册服务
Consul服务发现的使用方法:1. 在每台电脑上都以Client Mode的方式运行一个Consul代理, 这个代理只负责与Consul Cluster高效地交换最新注册信息(不参与Leader的选 ...
随机推荐
- mysql group by组内排序
mysql group by组内排序: 首先是组外排序: SELECT z.create_time,z.invoice_id from qf_invoice_log z where z ...
- 工作记录之 [ python请求url ] v s [ java请求url ]
背景: 模拟浏览器访问web,发送https请求url,为了实验需求需要获取ipv4数据包 由于不做后续的内容整理(有内部平台分析),故只要写几行代码请求发送https请求url列表中的url即可 开 ...
- TF:利用TF的train.Saver将训练好的variables(W、b)保存到指定的index、meda文件—Jason niu
import tensorflow as tf import numpy as np W = tf.Variable([[2,1,8],[1,2,5]], dtype=tf.float32, name ...
- AngularJS的Scope和Digest
Angular是一个成熟和强大的JavaScript框架.它也是一个比较庞大的框架,在熟练掌握之前,需要领会它提出的很多新概念.很多Web开发人员涌向Angular,有不少人面临同样的障碍.Diges ...
- format 用法
hon2.6开始,新增了一种格式化字符串的函数str.format(),可谓威力十足.那么,他跟之前的%型格式化字符串相比,有什么优越的存在呢?让我们来揭开它羞答答的面纱.语法 它通过{}和:来代替% ...
- Redis自学笔记:2.准备
第2章:准备 '纸上得来终觉浅,绝知此事要躬行'--陆游 2.2启动和停止redis 表2-1 redis可执行文件说明 文件名 说明 redis- server redis服务器 redis-cli ...
- BZOJ.4182.Shopping(点分治/dsu on tree 树形依赖背包 多重背包 单调队列)
BZOJ 题目的限制即:给定一棵树,只能任选一个连通块然后做背包,且每个点上的物品至少取一个.求花费为\(m\)时最大价值. 令\(f[i][j]\)表示在点\(i\),已用体积为\(j\)的最大价值 ...
- Java并发编程(二)-- 创建、运行线程
Java线程 Java线程类也是一个object类,它的实例都继承自java.lang.Thread或其子类. Java可以用如下方式创建一个线程: Tread thread = new Thread ...
- Scrapy基础(九)————将不定长度的URL进行固定长度写入Item中
前面讲到将每篇文章的URL写入Item,但是每个url的长度是不同的,可以在Item中设置一个字段怎样使得每个URL的长度相同,这就需要对每个URL进行md5运算,使得长度统一,再加入到设定的Item ...
- 【DWM1000】 code 解密9一 ANCHOR response poll message
根据上面TAG发送的代码,我直接找到如下代码 case RTLS_DEMO_MSG_TAG_POLL: { if(inst->mode == LISTENER) ...