C#重构方法:减少Switch语句数量的方案咨询
重构C#搜索类以消除重复Switch语句
嘿,这个重复的switch问题确实很常见,你的代码里三次基于model.Attribute的分支判断完全可以被收拢,让代码更简洁、易维护。我推荐用策略模式来重构,把每个搜索类型的专属逻辑封装成独立的策略类,彻底干掉冗余的switch。
第一步:定义搜索策略接口
先创建一个接口,把每个搜索类型需要实现的三个核心逻辑(获取存储过程名、添加参数、映射结果)抽象出来:
public interface ISearchStrategy { // 返回对应的存储过程名称 string GetStoredProcedureName(); // 根据SearchModel给SqlCommand添加参数 void AddParameters(SqlCommand cmd, SearchModel model); // 把SqlDataReader的数据映射到ResultModel void MapResult(SqlDataReader reader, ResultModel result); }
第二步:为每个搜索类型实现策略类
针对Users、Favorites、Email分别实现接口,每个类只负责自己的专属逻辑:
Users搜索策略
public class UsersSearchStrategy : ISearchStrategy { public string GetStoredProcedureName() => "GeneralUserSearch"; public void AddParameters(SqlCommand cmd, SearchModel model) { if (!string.IsNullOrWhiteSpace(model.Name)) cmd.Parameters.AddWithValue("Name", model.Name); if (!string.IsNullOrWhiteSpace(model.Username)) cmd.Parameters.AddWithValue("Username", model.Username); } public void MapResult(SqlDataReader reader, ResultModel result) { result.Users.Add(reader["User"]); } }
Favorites搜索策略
public class FavoritesSearchStrategy : ISearchStrategy { public string GetStoredProcedureName() => "UserFavorites"; public void AddParameters(SqlCommand cmd, SearchModel model) { cmd.Parameters.AddWithValue("Favorites", model.Favorites); } public void MapResult(SqlDataReader reader, ResultModel result) { result.User = reader["User"]; result.Favorites = reader["Favorites"]; } }
Email搜索策略
public class EmailSearchStrategy : ISearchStrategy { public string GetStoredProcedureName() => "EmailSearch"; public void AddParameters(SqlCommand cmd, SearchModel model) { cmd.Parameters.AddWithValue("Email", model.Email); } public void MapResult(SqlDataReader reader, ResultModel result) { result.User = reader["User"]; result.Email = reader["Email"]; } }
第三步:重构主方法,用字典映射策略
现在把原来的主方法里的switch全部替换成字典查找,代码一下子就清爽了:
// 静态字典,提前注册所有搜索策略 private static readonly Dictionary<string, ISearchStrategy> _searchStrategies = new Dictionary<string, ISearchStrategy> { { "Users", new UsersSearchStrategy() }, { "Favorites", new FavoritesSearchStrategy() }, { "Email", new EmailSearchStrategy() } }; public static SearchModel GetSearchResults(SearchModel model) { List<ResultModel> results = new List<ResultModel>(); try { // 查找对应策略,处理无效的Attribute情况 if (!_searchStrategies.TryGetValue(model.Attribute, out var strategy)) { model.ErrorMessage = $"无效的搜索类型:{model.Attribute}"; model.Results = results; return model; } using (SqlConnection conn = new SqlConnection("connection string")) { conn.Open(); using (SqlCommand cmd = AdoBase.GetSqlCommand(strategy.GetStoredProcedureName(), conn)) { // 调用策略添加参数 strategy.AddParameters(cmd, model); using (SqlDataReader reader = cmd.ExecuteReader()) { if (reader.HasRows) { while (reader.Read()) { ResultModel result = new ResultModel(); // 调用策略映射结果 strategy.MapResult(reader, result); results.Add(result); } } } } } } catch (Exception ex) { // 注意:原代码返回Exception是错误的(方法返回类型是SearchModel),这里改成记录错误信息 model.ErrorMessage = $"搜索失败:{ex.Message}"; } // 把结果赋值给model(假设SearchModel有Results属性) model.Results = results; return model; }
重构后的好处
- 彻底消除重复switch:所有分支逻辑都被封装到各自的策略类里,主方法只负责通用流程
- 符合开闭原则:以后新增搜索类型,只需要加新的策略类和字典项,不用修改主方法代码
- 职责单一:每个策略类只处理一种搜索类型的逻辑,代码更易读、易测试
- 可扩展性强:如果某个搜索类型需要调整逻辑,直接修改对应的策略类即可,不影响其他部分
另外提个小建议:原代码里的catch块直接返回ex是不符合方法返回类型的,我已经改成在model里设置错误信息,你可以根据实际需求调整错误处理逻辑。
内容的提问来源于stack exchange,提问作者CodePull
相关产品推荐
相关产品推荐

