解析 .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的选 ...
随机推荐
- 上传前端webuploader
多文件上传时,是有几个文件调用几次方法. 可以设置为单线程.
- Sublime Text3配置Lua运行环境
Sublime Text3配置Lua运行环境 前言 要问现在哪个编译器最能扛得住潮流,要数Sublime Text3了,由于它的轻量,插件丰富,美观,造就了一大批粉丝(本菜鸡也是哦) 在以前的工作中使 ...
- Python常用模块--re
Python内部的re--传闻中的正则模块,是无数初学者心中的噩梦,几乎到了谈正则色变的地步. 1.正则是干什么的 正则表达式,又称规则表达式.(英语:Regular Expression,在代码中常 ...
- CSS-变量
为什么使用 css variables 借用Scrimba上的: easier to get started (no transpiling) have access to the DOM 1.loc ...
- 解决win10 64位 + Python3 安装PyAutoIt报不是有效win32应用程序的办法
在win10 64位 + Python3的环境中,安装pyautoit第三方包的时候,报错提示为:不是有效win32应用程序.因为这个问题,进了python群,去寻求答案,却告知为,换32位的电脑,这 ...
- shell编程第四天
- Xamarin Essentials教程使用指南针Compass
Xamarin Essentials教程使用指南针Compass 指南针是一种确定地理方向的工具.在手机应用程序中,指南针通过手机的磁力计确定磁北极,提供手机方向信息.在Xamarin中,开发者可 ...
- BZOJ.3811.玛里苟斯(线性基)
BZOJ UOJ 感觉网上大部分题解对我这种数学基础差的人来说十分不友好...(虽然理解后也觉得没有那么难) 结合两篇写的比较好的详细写一写.如果有错要指出啊QAQ https://blog.csdn ...
- AGC 030D.Inversion Sum(DP 期望)
题目链接 \(Description\) 给定长为\(n\)的序列\(A_i\)和\(q\)次操作\((x,y)\).对于每次操作\((x,y)\),可以选择交换\(A_x,A_y\)两个数,也可以选 ...
- Ubuntu环境中的Android源代码下载
跟随“老罗的Android之旅”学习Android系统,首先得学会创建能用于编译Android源代码的环境. 文章参考:http://0xcc0xcd.com/p/books/978-7-121-18 ...