You need to enable JavaScript to run this app. C#泛型方法创建Binding实例报CS0417错误,如何实现该需求?
优惠活动
大模型
产品
解决方案
定价
更多

C#泛型方法创建Binding实例报CS0417错误,如何实现该需求?

报错原因

C# 泛型的 new() 约束仅支持无参数构造函数的调用,即便你限定了 T 继承自 System.ServiceModel.Channels.Binding 类型,也无法直接通过 new T(参数) 的语法调用带参构造函数,这是C#泛型的固有语法限制,和具体类型是否存在对应带参构造无关。

可行实现方案

方案1:反射调用带参构造(无需改动方法签名)

直接通过反射获取T的string参数构造函数执行,和你原有逻辑完全兼容:

public static T NewBinding2<T>(string pCfgName, string pCfgSuffix, string pAddr) where T : System.ServiceModel.Channels.Binding, new()
{
    T result = null;
    // 当pCfgSuffix不为空时,优先尝试带后缀的配置名
    string cfgId = (!string.IsNullOrEmpty(pCfgSuffix) ? StrUtils.IncludeTrailing(pCfgName, ".") + pCfgSuffix : pCfgName);
    // 尝试根据配置名创建Binding实例
    try 
    { 
        // 反射调用带string参数的构造函数
        var ctor = typeof(T).GetConstructor(new[] { typeof(string) });
        if (ctor != null)
        {
            result = (T)ctor.Invoke(new object[] { cfgId });
        }
    }
    catch (Exception ex1)
    {
        Trace.WriteLine(TrcLvl.TraceError, TrcLvl.TraceError ? string.Format("NewBinding<{0}>.1[{1}]({2}).ERR:{3}\nat {4}",
            typeof(T), cfgId, pAddr, ErrorUtils.FormatErrorMsg(ex1), ErrorUtils.FormatStackTrace(ex1)) : "");

        // 如果带后缀的创建失败,尝试不带后缀的配置名
        if (!string.IsNullOrEmpty(pCfgSuffix))
        {
            cfgId = pCfgName;
            try 
            {
                var ctor = typeof(T).GetConstructor(new[] { typeof(string) });
                if (ctor != null)
                {
                    result = (T)ctor.Invoke(new object[] { cfgId });
                }
            }
            catch (Exception ex2)
            {
                Trace.WriteLine(TrcLvl.TraceError, TrcLvl.TraceError ? string.Format("NewBinding<{0}>.2[{1}]({2}).ERR:{3}\nat {4}",
                    typeof(T), cfgId, pAddr, ErrorUtils.FormatErrorMsg(ex2), ErrorUtils.FormatStackTrace(ex2)) : "");
            }
        }

        if (result == null)
        {
            // 所有配置读取失败时,使用默认构造函数创建实例,手动设置名称
            result = new T();
            result.Name = cfgId;
        }
    }
    return result;
}

// 调用方式和原来完全一致
BasicHttpBinding bnd = NewBinding2<BasicHttpBinding>("bndBasicHttp", "ScreensApi", "http://....");

方案2:传入带参构造委托(性能优于反射)

你提到的 Func<string, T> 方案完全可用,内部生成的cfgId直接作为参数调用委托即可:

// 方法签名新增构造委托参数
public static T NewBinding2<T>(string pCfgName, string pCfgSuffix, string pAddr, Func<string, T> ctorFunc) where T : System.ServiceModel.Channels.Binding, new()
{
    T result = null;
    string cfgId = (!string.IsNullOrEmpty(pCfgSuffix) ? StrUtils.IncludeTrailing(pCfgName, ".") + pCfgSuffix : pCfgName);
    try 
    { 
        // 直接调用传入的构造委托
        result = ctorFunc(cfgId); 
    }
    catch (Exception ex1)
    {
        Trace.WriteLine(TrcLvl.TraceError, TrcLvl.TraceError ? string.Format("NewBinding<{0}>.1[{1}]({2}).ERR:{3}\nat {4}",
            typeof(T), cfgId, pAddr, ErrorUtils.FormatErrorMsg(ex1), ErrorUtils.FormatStackTrace(ex1)) : "");

        if (!string.IsNullOrEmpty(pCfgSuffix))
        {
            cfgId = pCfgName;
            try 
            { 
                result = ctorFunc(cfgId); 
            }
            catch (Exception ex2)
            {
                Trace.WriteLine(TrcLvl.TraceError, TrcLvl.TraceError ? string.Format("NewBinding<{0}>.2[{1}]({2}).ERR:{3}\nat {4}",
                    typeof(T), cfgId, pAddr, ErrorUtils.FormatErrorMsg(ex2), ErrorUtils.FormatStackTrace(ex2)) : "");
            }
        }

        if (result == null)
        {
            result = new T();
            result.Name = cfgId;
        }
    }
    return result;
}

// 调用时传入对应类型的带参构造函数即可
BasicHttpBinding bnd = NewBinding2<BasicHttpBinding>("bndBasicHttp", "ScreensApi", "http://....", cfg => new BasicHttpBinding(cfg));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 17:51:02