如何处理类型不兼容的对象集合?基于泛型表控制器场景
处理泛型控制器与多数据表类型集合的兼容问题
你已经搭建了一套基于抽象基类TableBase的数据表体系,还有泛型Controller<T>来对应处理每个数据表类型。现在的核心痛点是:当你拿到一个混合了TableA、TableB、TableC等不同子类的TableBase集合时,没办法直接用统一方式创建对应类型的泛型控制器——毕竟泛型类型在编译期就需要确定,而集合元素的具体类型要到运行时才明确。
下面给你几个实用的解决方案,你可以根据业务复杂度和扩展性需求选择:
方案1:模式匹配+类型分支(简单直接,适合类型少的场景)
遍历集合时,用C#的模式匹配判断每个元素的具体类型,针对性创建控制器并执行操作。这种方式代码直观,上手快:
// 示例混合类型集合 var tables = new List<TableBase> { new TableA(), new TableB(), new TableC() }; foreach (var table in tables) { switch (table) { case TableA a: var controllerA = new Controller<TableA>(a); controllerA.Synchronize(); break; case TableB b: var controllerB = new Controller<TableB>(b); controllerB.Synchronize(); break; case TableC c: var controllerC = new Controller<TableC>(c); controllerC.Synchronize(); break; default: throw new NotSupportedException($"不支持的数据表类型:{table.GetType().Name}"); } }
方案2:工厂模式(可扩展,适合类型较多的场景)
把创建控制器的逻辑封装到工厂类里,后续新增数据表类型时,只需要修改工厂的分支判断,符合开闭原则:
public static class TableControllerFactory { public static dynamic CreateController(TableBase table) { return table switch { TableA a => new Controller<TableA>(a), TableB b => new Controller<TableB>(b), TableC c => new Controller<TableC>(c), _ => throw new NotSupportedException($"不支持的数据表类型:{table.GetType().Name}") }; } } // 使用方式 foreach (var table in tables) { var controller = TableControllerFactory.CreateController(table); controller.Synchronize(); }
这里用dynamic是因为不同的Controller<T>属于不同类型,暂时没有统一的非泛型类型接收——如果想要更类型安全的写法,可以看方案3。
方案3:给控制器定义非泛型接口(优雅的类型安全方案)
给泛型控制器加一个非泛型接口,把Synchronize这类公共操作放到接口里,这样工厂就可以返回统一的接口类型,避免使用dynamic:
// 定义非泛型接口 public interface ITableController { void Synchronize(); } // 修改泛型控制器实现接口 public class Controller<T> : ITableController where T : TableBase { public Controller(T table) { table.TableName(); } public void Synchronize() { // 这里写针对T类型的同步逻辑 } } // 优化后的工厂类 public static class TableControllerFactory { public static ITableController CreateController(TableBase table) { return table switch { TableA a => new Controller<TableA>(a), TableB b => new Controller<TableB>(b), TableC c => new Controller<TableC>(c), _ => throw new NotSupportedException($"不支持的数据表类型:{table.GetType().Name}") }; } } // 类型安全的使用方式 foreach (var table in tables) { var controller = TableControllerFactory.CreateController(table); controller.Synchronize(); }
方案4:反射创建(适合动态扩展场景,性能稍弱)
如果你的数据表类型是动态加载的,没办法提前写死类型判断,可以用反射动态创建泛型控制器:
foreach (var table in tables) { var tableType = table.GetType(); // 构造泛型Controller<T>的类型 var controllerType = typeof(Controller<>).MakeGenericType(tableType); // 创建控制器实例并转换为接口类型 var controller = Activator.CreateInstance(controllerType, table) as ITableController; controller?.Synchronize(); }
这种方式不需要修改现有代码结构,但反射的性能比前几种方式差一些,适合类型数量不确定或动态扩展的场景。
内容的提问来源于stack exchange,提问作者beatnikthedan
相关产品推荐
相关产品推荐

