You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何减少相似依赖注入定义?用反射优化批量注入代码

How to Reduce Duplicate Handler Registration Code with Reflection (or Other Optimizations)

Great question! Manually registering every IHandler<T> and its corresponding implementation gets really tedious as your application grows—no one wants to write that repetitive AddTransient line dozens of times. Let’s break down a few solid approaches to clean this up:

1. Manual Reflection-Based Registration

You can use .NET’s reflection APIs to scan your assembly for all handler implementations and register them automatically. Here’s how to do it:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddServerSideBlazor();

    // Get the assembly where your handlers/MyClass types live
    var targetAssembly = typeof(MyClass1).Assembly;

    // Find all non-abstract, non-interface types that implement IHandler<>
    var handlerPairs = targetAssembly.GetTypes()
        .Where(type => !type.IsAbstract && !type.IsInterface)
        .Select(type => new
        {
            ImplementationType = type,
            HandlerInterface = type.GetInterfaces()
                .FirstOrDefault(iface => 
                    iface.IsGenericType && 
                    iface.GetGenericTypeDefinition() == typeof(IHandler<>))
        })
        .Where(pair => pair.HandlerInterface != null);

    // Register each handler-transient pair
    foreach (var pair in handlerPairs)
    {
        services.AddTransient(pair.HandlerInterface, pair.ImplementationType);
    }
}

Notes:

  • If your handlers are spread across multiple assemblies, adjust targetAssembly to include those (e.g., Assembly.Load("MyHandlersAssembly")).
  • This approach fully automates registration—add a new handler class, and it’ll get picked up without modifying this method.

2. Use the Scrutor Library (Simpler Reflection Wrapper)

Scrutor is a popular NuGet package that simplifies bulk dependency registration by wrapping reflection logic in a clean, fluent API. It’s less error-prone than writing raw reflection yourself.

First, install the package via NuGet:

Install-Package Scrutor
# Or via .NET CLI: dotnet add package Scrutor

Then update your ConfigureServices method:

using Scrutor;

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddServerSideBlazor();

    // Scan your assembly and register all IHandler<> implementations as transient
    services.Scan(scan => scan
        .FromAssemblyOf<MyClass1>() // Target the assembly with your handlers
        .AddClasses(classes => classes.AssignableTo(typeof(IHandler<>))) // Filter handler classes
        .AsImplementedInterfaces() // Register each class against its implemented interfaces
        .WithTransientLifetime()); // Set the service lifetime
}

Why Scrutor?

  • It handles edge cases (like types implementing multiple interfaces) gracefully.
  • You can easily adjust lifetimes (swap WithTransientLifetime for WithScopedLifetime or WithSingletonLifetime).
  • The fluent syntax makes the code readable and maintainable.

3. Manual Mapping Dictionary (For Controlled Registration)

If you prefer to avoid reflection entirely but still want to reduce repetitive code, you can centralize your handler mappings in a dictionary:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddServerSideBlazor();

    var handlerMappings = new Dictionary<Type, Type>
    {
        { typeof(IHandler<MyClass1>), typeof(AHandler) },
        { typeof(IHandler<MyClass2>), typeof(BHandler) },
        { typeof(IHandler<MyClass3>), typeof(CHandler) },
        // Add new mappings here as needed
    };

    foreach (var (interfaceType, implementationType) in handlerMappings)
    {
        services.AddTransient(interfaceType, implementationType);
    }
}

Pros:

  • No reflection overhead (minimal, but worth noting).
  • Full control over which handlers get registered—you won’t accidentally register unintended types.

Final Recommendation

If you want full automation and don’t mind adding a lightweight NuGet package, Scrutor is the way to go—it’s the most clean and maintainable option. If you can’t add third-party packages, the raw reflection approach works great too. The dictionary method is best for small apps where you want explicit control over registrations.

内容的提问来源于stack exchange,提问作者ca9163d9

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:25:25