欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

全面解析.NET中的依賴(lài)注入(DI)

 更新時(shí)間:2025年06月26日 08:48:48   作者:百錦再@新空間  
依賴(lài)注入是一種軟件設(shè)計(jì)模式,其核心思想是將對(duì)象依賴(lài)關(guān)系的管理交由外部容器負(fù)責(zé),而不是由對(duì)象自身管理,下面小編就來(lái)和大家詳細(xì)介紹一下依賴(lài)注入吧

一、依賴(lài)注入核心原理

1. 控制反轉(zhuǎn)(IoC)與DI關(guān)系

  • 控制反轉(zhuǎn)(IoC):框架控制程序流程,而非開(kāi)發(fā)者
  • 依賴(lài)注入(DI):IoC的一種實(shí)現(xiàn)方式,通過(guò)外部提供依賴(lài)對(duì)象

2. .NET DI核心組件

  • IServiceCollection:服務(wù)注冊(cè)容器
  • IServiceProvider:服務(wù)解析器
  • ServiceDescriptor:服務(wù)描述符(包含生命周期信息)

二、服務(wù)生命周期

三種生命周期類(lèi)型

生命周期描述適用場(chǎng)景
Transient每次請(qǐng)求創(chuàng)建新實(shí)例輕量級(jí)、無(wú)狀態(tài)服務(wù)
Scoped同一作用域內(nèi)共享實(shí)例Web請(qǐng)求上下文
Singleton全局單例配置服務(wù)、緩存
// 注冊(cè)示例
services.AddTransient<ITransientService, TransientService>();
services.AddScoped<IScopedService, ScopedService>();
services.AddSingleton<ISingletonService, SingletonService>();

三、DI容器實(shí)現(xiàn)原理

1. 服務(wù)注冊(cè)流程

public static IServiceCollection AddTransient<TService, TImplementation>(this IServiceCollection services)
{
    // 創(chuàng)建服務(wù)描述符
    var descriptor = new ServiceDescriptor(
        typeof(TService),
        typeof(TImplementation),
        ServiceLifetime.Transient);
    
    // 添加到集合
    services.Add(descriptor);
    return services;
}

2. 服務(wù)解析流程

public object GetService(Type serviceType)
{
    // 1. 查找服務(wù)描述符
    var descriptor = _descriptors.FirstOrDefault(d => d.ServiceType == serviceType);
    
    // 2. 根據(jù)生命周期創(chuàng)建實(shí)例
    if (descriptor.Lifetime == ServiceLifetime.Singleton)
    {
        if (_singletons.TryGetValue(serviceType, out var instance))
            return instance;
        
        instance = CreateInstance(descriptor);
        _singletons[serviceType] = instance;
        return instance;
    }
    // ...處理Scoped和Transient
}

四、高級(jí)實(shí)現(xiàn)方法

1. 工廠(chǎng)模式注冊(cè)

services.AddTransient<IService>(provider => {
    var otherService = provider.GetRequiredService<IOtherService>();
    return new ServiceImpl(otherService, "參數(shù)");
});

2. 泛型服務(wù)注冊(cè)

services.AddTransient(typeof(IRepository<>), typeof(Repository<>));

3. 多實(shí)現(xiàn)解決方案

// 注冊(cè)多個(gè)實(shí)現(xiàn)
services.AddTransient<IMessageService, EmailService>();
services.AddTransient<IMessageService, SmsService>();

// 解析時(shí)獲取所有實(shí)現(xiàn)
var services = provider.GetServices<IMessageService>();

五、ASP.NET Core中的DI集成

1. 控制器注入

public class HomeController : Controller
{
    private readonly ILogger _logger;
    
    public HomeController(ILogger<HomeController> logger)
    {
        _logger = logger; // 自動(dòng)注入
    }
}

2. 視圖注入

@inject IConfiguration Config
<p>當(dāng)前環(huán)境: @Config["Environment"]</p>

3. 中間件注入

public class CustomMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger _logger;
    
    public CustomMiddleware(
        RequestDelegate next,
        ILogger<CustomMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }
    
    public async Task InvokeAsync(HttpContext context)
    {
        // 使用注入的服務(wù)
        _logger.LogInformation("中間件執(zhí)行");
        await _next(context);
    }
}

六、自定義DI容器實(shí)現(xiàn)

1. 簡(jiǎn)易DI容器實(shí)現(xiàn)

public class SimpleContainer : IServiceProvider
{
    private readonly Dictionary<Type, ServiceDescriptor> _descriptors;
    
    public SimpleContainer(IEnumerable<ServiceDescriptor> descriptors)
    {
        _descriptors = descriptors.ToDictionary(x => x.ServiceType);
    }
    
    public object GetService(Type serviceType)
    {
        if (!_descriptors.TryGetValue(serviceType, out var descriptor))
            return null;
            
        if (descriptor.ImplementationInstance != null)
            return descriptor.ImplementationInstance;
            
        var type = descriptor.ImplementationType ?? descriptor.ServiceType;
        return ActivatorUtilities.CreateInstance(this, type);
    }
}

2. 屬性注入實(shí)現(xiàn)

public static class PropertyInjectionExtensions
{
    public static void AddPropertyInjection(this IServiceCollection services)
    {
        services.AddTransient<IStartupFilter, PropertyInjectionStartupFilter>();
    }
}

public class PropertyInjectionStartupFilter : IStartupFilter
{
    public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
    {
        return builder =>
        {
            builder.Use(async (context, nextMiddleware) =>
            {
                var endpoint = context.GetEndpoint();
                if (endpoint?.Metadata.GetMetadata<ControllerActionDescriptor>() is { } descriptor)
                {
                    var controller = context.RequestServices.GetRequiredService(descriptor.ControllerTypeInfo);
                    // 反射實(shí)現(xiàn)屬性注入
                    InjectProperties(controller, context.RequestServices);
                }
                await nextMiddleware();
            });
            next(builder);
        };
    }
    
    private void InjectProperties(object target, IServiceProvider services)
    {
        var properties = target.GetType().GetProperties()
            .Where(p => p.CanWrite && p.GetCustomAttribute<InjectAttribute>() != null);
            
        foreach (var prop in properties)
        {
            var service = services.GetService(prop.PropertyType);
            if (service != null)
                prop.SetValue(target, service);
        }
    }
}

七、最佳實(shí)踐

1. 服務(wù)設(shè)計(jì)原則

  • 遵循顯式依賴(lài)原則
  • 避免服務(wù)定位 器模式(反模式)
  • 保持服務(wù)輕量級(jí)

2. 常見(jiàn)陷阱

// 錯(cuò)誤示例:捕獲Scoped服務(wù)到Singleton中
services.AddSingleton<IBackgroundService>(provider => {
    var scopedService = provider.GetRequiredService<IScopedService>(); // 危險(xiǎn)!
    return new BackgroundService(scopedService);
});

// 正確做法:使用IServiceScopeFactory
services.AddSingleton<IBackgroundService>(provider => {
    var scopeFactory = provider.GetRequiredService<IServiceScopeFactory>();
    return new BackgroundService(scopeFactory);
});

八、性能優(yōu)化

1. 避免過(guò)度注入

// 不好:注入過(guò)多服務(wù)
public class OrderService(
    ILogger logger,
    IEmailService emailService,
    ISmsService smsService,
    IRepository repo,
    ICache cache,
    IConfig config)
{
    // ...
}

// 改進(jìn):使用聚合服務(wù)
public class OrderService(
    ILogger logger,
    INotificationService notification,
    IOrderInfrastructure infra)
{
    // ...
}

2. 編譯時(shí)注入

[RegisterTransient(typeof(IMyService))]
public class MyService : IMyService
{
    // ...
}

// 使用Source Generator自動(dòng)生成注冊(cè)代碼
static partial class ServiceRegistration
{
    static partial void AddGeneratedServices(IServiceCollection services)
    {
        services.AddTransient<IMyService, MyService>();
    }
}

.NET的依賴(lài)注入系統(tǒng)是框架的核心基礎(chǔ)設(shè)施,理解其原理和實(shí)現(xiàn)方式有助于編寫(xiě)更可測(cè)試、更松耦合的應(yīng)用程序。

到此這篇關(guān)于全面解析.NET中的依賴(lài)注入(DI)的文章就介紹到這了,更多相關(guān).NET依賴(lài)注入DI內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論