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

Microsoft.Practices.Unity的ResolverOverride在MSDI中的等效替代方案

迁移Unity依赖注入至MS DI:替代ResolverOverride方案

一、手动实现参数覆盖逻辑(替代ParameterOverride)

Microsoft.Extensions.DependencyInjection没有直接对应Unity的ResolverOverride机制,但可以通过反射解析构造函数+ActivatorUtilities(或直接调用构造函数)实现相同的参数覆盖功能。以下是可直接复用的扩展方法:

using Microsoft.Extensions.DependencyInjection;
using System.Reflection;

public static class ServiceProviderExtensions
{
    public static object ResolveWithOverrides(this IServiceProvider provider, Type serviceType, string? serviceName = null, IDictionary<string, object>? parameterOverrides = null)
    {
        // 处理命名服务(.NET 8+支持Keyed服务)
        object? instance = null;
        if (!string.IsNullOrEmpty(serviceName))
        {
            instance = provider.GetKeyedService(serviceType, serviceName);
        }
        else
        {
            instance = provider.GetService(serviceType);
        }

        // 无参数覆盖时直接返回已注册实例
        if (instance != null && parameterOverrides == null)
        {
            return instance;
        }

        // 获取目标类型参数最多的公共构造函数(对齐Unity默认逻辑)
        var constructor = serviceType.GetConstructors(BindingFlags.Public | BindingFlags.Instance)
            .OrderByDescending(c => c.GetParameters().Length)
            .FirstOrDefault();

        if (constructor == null)
        {
            throw new InvalidOperationException($"类型 {serviceType.FullName} 未找到公共构造函数");
        }

        var parameters = constructor.GetParameters();
        var parameterValues = new object[parameters.Length];

        for (int i = 0; i < parameters.Length; i++)
        {
            var param = parameters[i];
            // 优先使用参数覆盖值
            if (parameterOverrides != null && parameterOverrides.TryGetValue(param.Name, out var overrideValue))
            {
                parameterValues[i] = overrideValue;
            }
            else
            {
                // 从DI容器获取参数值,处理可选参数
                var paramValue = provider.GetService(param.ParameterType);
                if (paramValue == null && param.IsOptional)
                {
                    parameterValues[i] = param.DefaultValue!;
                }
                else if (paramValue == null)
                {
                    throw new InvalidOperationException($"无法解析构造函数参数 {param.Name}(类型:{param.ParameterType.FullName})");
                }
                else
                {
                    parameterValues[i] = paramValue;
                }
            }
        }

        // 创建并返回实例
        return constructor.Invoke(parameterValues);
    }

    // 泛型简化版本
    public static T ResolveWithOverrides<T>(this IServiceProvider provider, string? serviceName = null, IDictionary<string, object>? parameterOverrides = null)
    {
        return (T)ResolveWithOverrides(provider, typeof(T), serviceName, parameterOverrides);
    }
}

使用示例

// 注册命名服务(.NET 8+)
services.AddKeyedTransient<IMyService, MyService>("NamedService");

// 解析时指定参数覆盖
var provider = services.BuildServiceProvider();
var overrides = new Dictionary<string, object> { { "customParam", "overrideValue" } };
var instance = provider.ResolveWithOverrides<IMyService>("NamedService", overrides);

二、获取Unity ParameterOverride源代码

Unity容器是开源项目,ParameterOverride类的源代码位于UnityContainer仓库的Unity/Resolution/ParameterOverride.cs文件中。其核心逻辑是实现ResolverOverride抽象类,在解析过程中匹配参数名并替换对应的值,你可以参考该逻辑扩展自己的参数覆盖实现(比如支持按类型覆盖的DependencyOverride)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 12:23:24