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

如何在StructureMap中按ExplicitArguments类型选择构造函数?

解决DI容器中根据ExplicitArguments自动选择构造函数的问题

看起来你遇到的核心问题是容器没有正确识别你通过ExplicitArguments传入的NetworkData实例,反而错误地尝试使用带有DefaultData参数的构造函数,进而因为DefaultData的构造参数缺失抛出异常。下面我来帮你一步步解决这个问题:

问题分析

从异常信息能明确看出:容器默认的构造函数选择逻辑没有优先匹配你显式传入的参数类型——它直接选中了优先级较高(比如声明顺序靠前)的Foo(IContainer, DefaultData)构造函数,完全忽略了你传入的NetworkData应该对应Foo(IContainer, NetworkData)这个构造函数。

解决方案:自定义构造函数选择器

你提到尝试过自定义IConstructorSelector但无法获取传入的参数类型,其实可以通过IContext对象拿到ExplicitArguments,然后根据里面的参数类型匹配最合适的构造函数。

1. 实现自定义构造函数选择器

public class ExplicitArgumentMatchingSelector : IConstructorSelector
{
    public ConstructorInfo SelectConstructor(Type type, IContext context)
    {
        var explicitArgs = context.ExplicitArguments;
        // 如果没有显式参数, fallback到默认选择逻辑
        if (explicitArgs == null || explicitArgs.Count == 0)
        {
            return new DefaultConstructorSelector().SelectConstructor(type, context);
        }

        // 获取当前类型的所有公共实例构造函数
        var constructors = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance);
        
        foreach (var ctor in constructors)
        {
            var parameters = ctor.GetParameters();
            bool isMatch = true;

            foreach (var param in parameters)
            {
                // 跳过IContainer类型(容器可以自行解析)
                if (param.ParameterType == typeof(IContainer))
                {
                    continue;
                }
                
                // 检查显式参数中是否包含当前参数的类型
                if (!explicitArgs.ContainsKey(param.ParameterType))
                {
                    isMatch = false;
                    break;
                }
            }

            // 找到完全匹配的构造函数,直接返回
            if (isMatch)
            {
                return ctor;
            }
        }

        // 如果没有找到匹配的,使用默认选择器
        return new DefaultConstructorSelector().SelectConstructor(type, context);
    }
}

2. 注册自定义选择器到容器

在创建容器实例后,替换默认的构造函数选择器:

var container = new Container();
// 替换为我们的自定义选择器
container.Options.ConstructorSelector = new ExplicitArgumentMatchingSelector();

// 正常传入显式参数
ExplicitArguments args = new ExplicitArguments();
args.Set(new NetworkData(new decimal(1.3D), 'f'));
var instance = container.GetInstance<Foo>(args);

// 此时instance.Location应该会是"NetworkData",符合预期

额外说明

  • 异常中提到DefaultData有一个带String和Int32参数的构造函数,但你提供的代码里DefaultData是无参的,这可能是你实际代码和示例的不一致——不过没关系,自定义选择器会跳过这个构造函数,直接匹配你传入的NetworkData对应的构造函数,从根源避免这个错误。
  • 这个选择器是通用的,不仅适用于Foo类,其他类只要有类似多构造函数+显式参数的场景,都可以复用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:53:20