如何在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
相关产品推荐
相关产品推荐

