.net core DI注入
第三方日志
最初使用serilog组件,做日志记录工具,有了以下插件代码:
public static class ServiceHostBuilderExtensions { public static IServiceCollection UseSeriLog(this IServiceCollection collection, Serilog.ILogger logger = null, bool dispose = false, LoggerProviderCollection providers = null) { if (providers != null) { collection.AddSingleton<ILoggerFactory>(services => { var factory = new SerilogLoggerFactory(logger, dispose, providers); foreach (var provider in services.GetServices<ILoggerProvider>()) factory.AddProvider(provider); return factory; }); } else { collection.AddSingleton<ILoggerFactory>(services => new SerilogLoggerFactory(logger, dispose)); } ConfigureServices(collection, logger); return collection; } static void ConfigureServices(IServiceCollection collection, Serilog.ILogger logger) { if (collection == null) throw new ArgumentNullException(nameof(collection)); if (logger != null) { collection.AddSingleton(logger); } } }
.net core 使用 webhost 或者通用主机ihost,在controller或者自定义host服务里,logger都正常的获取到了。
public class TimedHostedService : BackgroundService { private readonly ILogger _logger; private Timer _timer; public TimedHostedService(ILogger<TimedHostedService> logger) { this._logger = logger; } protected override Task ExecuteAsync(CancellationToken stoppingToken) { _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5)); return Task.CompletedTask; } private void DoWork(object state) { _logger.LogInformation(string.Format("[{0:yyyy-MM-dd hh:mm:ss}] Timed Background Service is working.", DateTime.Now)); } public override Task StopAsync(CancellationToken cancellationToken) { _logger.LogInformation("Timed Background Service is stopping."); _timer?.Change(Timeout.Infinite, 0); return Task.CompletedTask; } public override void Dispose() { _timer?.Dispose(); base.Dispose(); } }
控制台程序写下了如下测试代码:
static void Main(string[] args) { var builder = new ServiceCollection() .AddTransient<IFoo, Foo>() .AddTransient<IGux, Gux>() .AddLogging() .UseSeriLog() .BuildServiceProvider(); var log= builder.GetService<Microsoft.Extensions.Logging.ILogger>();
var m = builder.GetServices<IBar>(); }
public interface IFoo { }
public interface IBar { }
public class Foo : IFoo { }
public class Bar: IBar
{
public Gux(IFoo foo, Microsoft.Extensions.Logging.ILogger<Gux> logger)
{
Console.WriteLine("Test ");
}
}
得到的log是空。这里的原因是AddLogging()里注册的是泛型。
CORE DI
服务注册
- ServiceCollection
- ServiceProvider
1.Add
先看IserviceCollection定义:
public interface IServiceCollection : IList<ServiceDescriptor>{}
真正注册时使用的是
ServiceCollection().AddSingleton<>().AddTransient<>().AddScoped<>()
服务添加时,构建ServiceDescriptor(serviceType, implementationType, lifetime), IServiceCollection.add( ServiceDescriptor);
2.Builder
我们将相应的服务注册到ServiceCollection对象之上,然后BuildServiceProvider 创建的ServiceProvider 。
服务构建:ServiceProvider 内部会构建相应的 ServiceProviderEngine 它内部会创建运行时解析器,比如:RuntimeServiceProviderEngine
internal class RuntimeServiceProviderEngine : ServiceProviderEngine { public RuntimeServiceProviderEngine(IEnumerable<ServiceDescriptor> serviceDescriptors, IServiceProviderEngineCallback callback) : base(serviceDescriptors, callback) { } protected override Func<ServiceProviderEngineScope, object> RealizeService(ServiceCallSite callSite) { return scope => { Func<ServiceProviderEngineScope, object> realizedService = p => RuntimeResolver.Resolve(callSite, p); RealizedServices[callSite.ServiceType] = realizedService; return realizedService(scope); }; } }
internal abstract class ServiceProviderEngine : IServiceProviderEngine, IServiceScopeFactory { private readonly IServiceProviderEngineCallback _callback; private readonly Func<Type, Func<ServiceProviderEngineScope, object>> _createServiceAccessor; private bool _disposed; protected ServiceProviderEngine(IEnumerable<ServiceDescriptor> serviceDescriptors, IServiceProviderEngineCallback callback) { _createServiceAccessor = CreateServiceAccessor; _callback = callback; Root = new ServiceProviderEngineScope(this); RuntimeResolver = new CallSiteRuntimeResolver(); CallSiteFactory = new CallSiteFactory(serviceDescriptors); CallSiteFactory.Add(typeof(IServiceProvider), new ServiceProviderCallSite()); CallSiteFactory.Add(typeof(IServiceScopeFactory), new ServiceScopeFactoryCallSite()); RealizedServices = new ConcurrentDictionary<Type, Func<ServiceProviderEngineScope, object>>(); } internal ConcurrentDictionary<Type, Func<ServiceProviderEngineScope, object>> RealizedServices { get; } internal CallSiteFactory CallSiteFactory { get; } protected CallSiteRuntimeResolver RuntimeResolver { get; } public ServiceProviderEngineScope Root { get; } public IServiceScope RootScope => Root; public void ValidateService(ServiceDescriptor descriptor) { if (descriptor.ServiceType.IsGenericType && !descriptor.ServiceType.IsConstructedGenericType) { return; } try { var callSite = CallSiteFactory.GetCallSite(descriptor, new CallSiteChain()); if (callSite != null) { _callback?.OnCreate(callSite); } } catch (Exception e) { throw new InvalidOperationException($"Error while validating the service descriptor '{descriptor}': {e.Message}", e); } } public object GetService(Type serviceType) => GetService(serviceType, Root); protected abstract Func<ServiceProviderEngineScope, object> RealizeService(ServiceCallSite callSite);
下面是一个ServiceProvider的简单对象图
Service GetService Resolve
ServiceProvider 服务提取的主要对象,ServiceProviderEngineScope
- CallSiteVisitor
- ServiceCallSite
- CallSiteChain
作者:RunStone
出处:https://www.cnblogs.com/RunStone/p/11904636.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构