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

如何泛化签名几乎相同的C#方法?

重构重复的UISchemaBuilder添加方法

问题背景

目前有一组UISchemaBuilder的添加方法,每个方法签名高度相似,都接收一个继承自UISchemaParameters的参数类,最终都调用同一个私有Add方法:

public UISchemaBuilder AddText(UISchemaTextParameters parameters) => Add(parameters);
public UISchemaBuilder AddTextLine(UISchemaTextLineParameters parameters) => Add(parameters);
public UISchemaBuilder AddTextArea(UISchemaTextAreaParameters parameters) => Add(parameters);
// 更多类似方法...

私有Add方法实现如下:

private UISchemaBuilder Add(UISchemaParameters parameters)
{
   CreateUISchemaItem(
     parameters.Name,
     parameters.Title,
     parameters.IsRequired,
     parameters.IsReadOnly,
     parameters.IsMultiple,
     parameters.UIControlGet());

   return this;
}

所有参数类均继承自抽象类UISchemaParameters:

public abstract class UISchemaParameters
{
    protected UISchemaParameters() { }

    protected UISchemaParameters(NameLocalizedTitle nameTitle)
    {
        Name = nameTitle.Name;
        Title = nameTitle.Title;
    }

    public string Name { get; set; }
    public string Title { get; set; }
    public bool? IsReadOnly { get; set; }
    public bool? IsRequired { get; set; }
    public bool? IsMultiple { get; set; }

    public abstract UIControlAttribute UIControlGet();
}

示例参数类(如UISchemaTextAreaParameters):

public class UISchemaTextAreaParameters : UISchemaParameters
{
     public UISchemaTextAreaParameters() {}
     
     public UISchemaTextAreaParameters(NameLocalizedTitle nameTitle)
         : base(nameTitle)
     {
     }

     public uint? MaxLength {get;set;}

     public override UIControlAttribute UIControlGet() =>
        new UIControlStringAttribute()
     {
        Parameters = new UISchemaStringFieldParameters
        {
            MaxLength = MaxLength
        },
        IsMultiple = true
     };
}

现在需要重构这些重复的AddXXX方法,消除代码冗余。


重构方案

方案1:用泛型方法替代多个重载

直接提供一个泛型版的Add方法,约束泛型参数必须继承自UISchemaParameters,这样就能一次性替代所有AddXXX方法:

public UISchemaBuilder Add<TParameters>(TParameters parameters) 
    where TParameters : UISchemaParameters
{
    return Add(parameters); // 直接复用原私有Add方法逻辑
}

调用时编译器会自动推断泛型类型,写法简洁且保留类型安全:

builder.Add(new UISchemaTextParameters { Name = "username", Title = "用户名" });
builder.Add(new UISchemaTextAreaParameters { Name = "desc", Title = "描述", MaxLength = 500 });

如果想保留AddText这类语义化命名方法来提升可读性,只需保留简单的包装即可,无需重复逻辑:

public UISchemaBuilder AddText(UISchemaTextParameters parameters) => Add(parameters);
public UISchemaBuilder AddTextArea(UISchemaTextAreaParameters parameters) => Add(parameters);
// 其余方法同理,仅做类型转发

方案2:静态工厂简化参数创建(可选)

如果参数初始化步骤较多,可以给每个参数类添加静态工厂方法,减少手动创建对象的代码:

public class UISchemaTextAreaParameters : UISchemaParameters
{
    // 原有构造函数...

    public static UISchemaTextAreaParameters Create(string name, string title, uint? maxLength = null)
    {
        return new UISchemaTextAreaParameters
        {
            Name = name,
            Title = title,
            MaxLength = maxLength
        };
    }
}

调用时可以直接用工厂方法生成参数:

builder.Add(UISchemaTextAreaParameters.Create("desc", "描述", 500));

方案3:委托配置的泛型方法(进阶)

如果希望参数配置更连贯,可以提供一个带委托的泛型方法,直接在方法内创建并配置参数:

public UISchemaBuilder Add<TParameters>(Action<TParameters> configure) 
    where TParameters : UISchemaParameters, new()
{
    var parameters = new TParameters();
    configure(parameters);
    return Add(parameters);
}

调用时无需手动实例化参数,直接通过委托配置属性:

builder.Add<UISchemaTextAreaParameters>(p => 
{
    p.Name = "desc";
    p.Title = "描述";
    p.MaxLength = 500;
    p.IsRequired = true;
});

总结

最直接的重构方式是方案1的泛型方法,能彻底消除重复的AddXXX方法,同时保留类型安全。如果需要保留原有语义化方法名,可以保留简单的包装;如果想优化调用体验,可以结合方案2或方案3进一步简化参数创建流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 00:37:35