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

如何在C#中通过接口调用抽象静态方法?非反射优雅方案

解决方案

首先修正你原代码中的一个错误:使用IsSubclassOf(typeof(IBuildable))无法正确筛选出实现接口的类(该方法仅适用于类继承关系),正确的筛选逻辑应该是:

private static IReadOnlyDictionary<string, Type> buildableTypes =
  typeof(IBuildable).Assembly.GetTypes()
    .Where(t => typeof(IBuildable).IsAssignableFrom(t) && t.IsClass && !t.IsAbstract)
    .ToDictionary(t => t.Name, t => t);

针对你的需求,提供两种比反射更优雅高效的实现方式:

方案一:预编译委托(性能最优)

通过反射一次性获取每个类型的IsBuildable方法,编译为委托并缓存,后续调用直接使用委托,避免重复反射开销:

// 缓存每个类型对应的IsBuildable委托
private static readonly Dictionary<Type, Func<string, bool>> _isBuildableDelegates = new();

private static Func<string, bool> GetIsBuildableDelegate(Type type)
{
    if (_isBuildableDelegates.TryGetValue(type, out var func))
        return func;

    var method = type.GetMethod(nameof(IBuildable.IsBuildable), BindingFlags.Public | BindingFlags.Static);
    if (method == null)
        throw new InvalidOperationException($"类型 {type.Name} 未实现静态抽象方法 IsBuildable");

    var funcInstance = (Func<string, bool>)Delegate.CreateDelegate(typeof(Func<string, bool>), method);
    _isBuildableDelegates[type] = funcInstance;
    return funcInstance;
}

// 筛选逻辑
var @params = "目标参数";
var currentlyBuildableTypes = buildableTypes.Values
    .Where(t => GetIsBuildableDelegate(t)(@params));

该方案仅在首次调用每个类型时触发一次反射,后续调用性能接近直接调用静态方法,适合高频调用场景。

方案二:动态调用(代码最简洁)

利用C#的动态类型直接调用静态抽象方法,无需提前缓存,代码更简洁,但每次调用会有动态解析的开销,适合低频调用场景:

var @params = "目标参数";
var currentlyBuildableTypes = buildableTypes.Values
    .Where(t => ((dynamic)t).IsBuildable(@params));

注意:如果某个类型未正确实现IsBuildable静态方法,该方案会抛出运行时异常,需确保所有实现类都符合接口要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 14:40:21