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

.NET基于類名約定的自動依賴注入最佳實踐指南

 更新時間:2025年06月25日 09:29:34   作者:得想辦法娶到那個女人  
本文詳解.NET自動依賴注入技術,通過類名約定自動識別服務類與接口,支持Transient/Scoped/Singleton生命周期,提供注冊示例與混合策略,簡化服務注冊流程,提升開發(fā)效率,本文給大家介紹的非常詳細,感興趣的朋友一起看看吧

?? .NET基于類名約定的自動依賴注入完整指南

基于類名約定的自動依賴注入可大幅減少手動注冊服務的工作量,本文將通過清晰的結(jié)構、美觀的排版和豐富的示例,幫助你快速掌握這一實用技術。

?? 核心特性概覽

特性說明
類名約定自動識別以 Service 結(jié)尾的類(不區(qū)分大小寫)
接口優(yōu)先匹配優(yōu)先注冊到 I{ClassName} 形式的接口(如 UserServiceIUserService
多生命周期支持支持 Transient/Scoped/Singleton 三種生命周期
靈活掃描控制可指定任意程序集或默認掃描調(diào)用程序集
無接口自注冊自動注冊未實現(xiàn)接口的類為自身類型

?? 完整代碼實現(xiàn)(含所有重載)

using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;
using System.Reflection;
/// <summary>
/// 依賴注入擴展方法集合(基于類名約定)
/// </summary>
public static class ServiceCollectionExtensions
{
    /// <summary>
    /// 自動注冊以"Service"結(jié)尾的類(默認Transient生命周期)
    /// </summary>
    public static IServiceCollection AutoRegisterServices(
        this IServiceCollection services,
        Assembly assembly = null)
    {
        assembly ??= Assembly.GetCallingAssembly();
        // 掃描規(guī)則:公共類、非抽象、非泛型、類名以Service結(jié)尾
        var serviceTypes = assembly.GetTypes()
            .Where(t => 
                t.IsClass && !t.IsAbstract && t.IsPublic &&
                !t.ContainsGenericParameters &&
                t.Name.EndsWith("Service", StringComparison.OrdinalIgnoreCase))
            .ToArray();
        // 注冊服務到容器
        foreach (var implType in serviceTypes)
        {
            var interfaces = implType.GetInterfaces();
            if (interfaces.Any())
            {
                // 匹配I{ClassName}接口(如UserService→IUserService)
                var matchingInterface = interfaces.FirstOrDefault(i => 
                    i.Name == "I" + implType.Name);
                if (matchingInterface != null)
                {
                    services.AddTransient(matchingInterface, implType);
                }
                else
                {
                    // 注冊到所有實現(xiàn)的接口
                    foreach (var @interface in interfaces)
                    {
                        services.AddTransient(@interface, implType);
                    }
                }
            }
            else
            {
                // 無接口時注冊自身
                services.AddTransient(implType);
            }
        }
        return services;
    }
    /// <summary>
    /// 自動注冊以"Service"結(jié)尾的類(支持自定義生命周期)
    /// </summary>
    public static IServiceCollection AutoRegisterServices(
        this IServiceCollection services,
        ServiceLifetime lifetime,
        Assembly assembly = null)
    {
        assembly ??= Assembly.GetCallingAssembly();
        var serviceTypes = GetServiceTypes(assembly);
        foreach (var implType in serviceTypes)
        {
            var interfaces = implType.GetInterfaces();
            var descriptor = CreateServiceDescriptor(implType, interfaces, lifetime);
            services.Add(descriptor);
        }
        return services;
    }
    // 輔助方法:獲取服務類型(提取公共邏輯)
    private static Type[] GetServiceTypes(Assembly assembly) =>
        assembly.GetTypes()
            .Where(t => 
                t.IsClass && !t.IsAbstract && t.IsPublic &&
                !t.ContainsGenericParameters &&
                t.Name.EndsWith("Service", StringComparison.OrdinalIgnoreCase))
            .ToArray();
    // 輔助方法:創(chuàng)建服務描述符(提取公共邏輯)
    private static ServiceDescriptor CreateServiceDescriptor(
        Type implType, Type[] interfaces, ServiceLifetime lifetime)
    {
        if (interfaces.Any())
        {
            var matchingInterface = interfaces.FirstOrDefault(i => 
                i.Name == "I" + implType.Name);
            if (matchingInterface != null)
            {
                return new ServiceDescriptor(matchingInterface, implType, lifetime);
            }
            // 返回第一個接口(避免注冊多個描述符)
            return new ServiceDescriptor(interfaces[0], implType, lifetime);
        }
        return new ServiceDescriptor(implType, implType, lifetime);
    }
}

?? 使用示例(清晰排版)

1. 在ASP.NET Core中注冊(Program.cs

var builder = WebApplication.CreateBuilder(args);
// 方式1:默認Transient(掃描調(diào)用程序集)
builder.Services.AutoRegisterServices();
// 方式2:指定Scoped生命周期
builder.Services.AutoRegisterServices(ServiceLifetime.Scoped);
// 方式3:掃描指定程序集(如業(yè)務層)
var businessAssembly = Assembly.Load("MyBusinessLayer");
builder.Services.AutoRegisterServices(ServiceLifetime.Singleton, businessAssembly);
var app = builder.Build();

2. 服務類示例(符合約定的實現(xiàn))

// ? 示例1:接口匹配型服務
public interface IUserService { string GetInfo(); }
public class UserService : IUserService 
{
    public string GetInfo() => "User Service Running";
}
// ? 示例2:多接口實現(xiàn)服務
public interface IAuthService { void Login(); }
public interface ILogService { void WriteLog(string msg); }
public class AuthService : IAuthService, ILogService 
{
    public void Login() { /* 登錄邏輯 */ }
    public void WriteLog(string msg) { /* 日志邏輯 */ }
}
// ? 示例3:無接口自注冊服務
public class DataService 
{
    public void ProcessData() { /* 數(shù)據(jù)處理 */ }
}
// ? 示例4:不符合約定的類(不會被注冊)
public class ServiceHelper { }        // 類名不以Service結(jié)尾
public abstract class BaseService { } // 抽象類

?? 擴展優(yōu)化方案(帶emoji標記)

1. ?? 基于類名的生命周期自動識別

private static ServiceLifetime GetLifetimeFromName(string className)
{
    if (className.Contains("Singleton", StringComparison.OrdinalIgnoreCase))
        return ServiceLifetime.Singleton;
    if (className.Contains("Scoped", StringComparison.OrdinalIgnoreCase))
        return ServiceLifetime.Scoped;
    return ServiceLifetime.Transient;
}

2. ?? 特性標記增強控制

[AttributeUsage(AttributeTargets.Class)]
public class AutoRegisterAttribute : Attribute 
{
    public ServiceLifetime Lifetime { get; set; } = ServiceLifetime.Transient;
    public bool IsEnabled { get; set; } = true;
}

3. ? 緩存掃描結(jié)果提升性能

private static readonly object LockObj = new();
private static Type[] _cachedServiceTypes;
private static Type[] GetCachedServiceTypes(Assembly assembly)
{
    if (_cachedServiceTypes == null)
    {
        lock (LockObj)
        {
            _cachedServiceTypes = assembly.GetTypes()
                .Where(t => /* 掃描規(guī)則 */)
                .ToArray();
        }
    }
    return _cachedServiceTypes;
}

?? 最佳實踐指南

  1. ?? 混合注冊策略

    • 核心服務(如DbContext)手動注冊:
      services.AddDbContext<AppDbContext>(options => {...});
    • 業(yè)務服務自動注冊:
      builder.Services.AutoRegisterServices();

?? 精準掃描范圍

// 僅掃描當前程序集中的服務
builder.Services.AutoRegisterServices(typeof(UserService).Assembly);

? 單元測試驗證

[Fact]
public void Should_Resolve_Service_By_Convention()
{
    var services = new ServiceCollection();
    services.AutoRegisterServices(typeof(IAuthService).Assembly);
    var provider = services.BuildServiceProvider();
    var service = provider.GetService<IAuthService>();
    Assert.NotNull(service);
}

到此這篇關于.NET基于類名約定的自動依賴注入完整指南的文章就介紹到這了,更多相關.net自動依賴注入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論