在某个项目当中,使用的使Dapper+WebApi进行构建的,在进行一些列表查询的时候需要根据不同的State来构建不同的SQL语句。之前是直接使用的switch来一个个匹配,需求增加的话,又得再加一个case。长久以往,整个查询接口臃肿不堪,离职前夕终于看不下去了,重构了一番,兹此记录。
#原结构
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleTest
{
public class Product
{
public string Name { get; set; }
public double Price { get; set; }
}
class Program
{
static void Main(string[] args)
{
}
public List<Product> GetByStateToList(int ConditionState)
{
StringBuilder _queryString = new StringBuilder();
switch (ConditionState)
{
case 1:
_queryString.Append("查询1");
break;
case 2:
_queryString.Append("查询2");
break;
case 3:
_queryString.Append("查询3");
break;
default:
_queryString.Append("查询4");
break;
}
var _queryResult = QueryDatabase(_queryString.ToString());
return _queryResult;
}
public List<Product> QueryDatabase(string queryStr)
{
// .....查询处理
return new List<Product>();
}
}
}弊端十分明显,这里我是简化了查询语句,实际情况使每个case至少有十几行代码用于构建查询语句,随着业务变更不断加快,那么我们的GetByStateToList也会变得越来越臃肿,难以维护。
#那么如何重构呢?
#第一步,拆!!!
臃肿的原因就是因为在这个函数内部塞了太多的语句和分支条件,那么我们首先要把每个查询语句构建分离成一个类,将查询语句的构建放在这个独立的类内部进行操作。
#第二步,统一接口
所有构建SQL语句的类都会有一个Build方法,这个方法用于构建具体的SQL语句,那么我们可以通过一个统一的接口来调用这个Build进行操作。
#第三步,自动匹配
要实现自动匹配,每个类需要在其内部维护一个State常量,这个常量用于判断什么State实例化什么构造类。
下面我们就来实战演练了
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
namespace ConsoleTest
{
public class Product
{
public string Name { get; set; }
public double Price { get; set; }
}
public abstract class SQLBuilder
{
private static List<SQLBuilder> _builders = null;
public int State { get; protected set; }
public static ISQLBuilder GetSQLBuilder(int state)
{
if (_builders == null)
{
_builders = new List<SQLBuilder>();
var _types = Assembly.GetExecutingAssembly().GetTypes();
foreach (var _type in _types)
{
if (_type.GetInterface(typeof(ISQLBuilder).FullName) != null)
{
_builders.Add(Activator.CreateInstance(_type) as SQLBuilder);
}
}
}
var _builder = _builders.Where(x => x.State == state).FirstOrDefault();
return _builder as ISQLBuilder;
}
}
public interface ISQLBuilder
{
string Build();
}
public class SQLBuilderNo1 : SQLBuilder, ISQLBuilder
{
public SQLBuilderNo1() => State = 1;
public string Build() => "查询1";
}
public class SQLBuilderNo2 : SQLBuilder, ISQLBuilder
{
public SQLBuilderNo2() => State = 2;
public string Build() => "查询2";
}
public class SQLBuilderNo3 : SQLBuilder, ISQLBuilder
{
public SQLBuilderNo3() => State = 3;
public string Build() => "查询3";
}
class Program
{
static void Main(string[] args)
{
ISQLBuilder _builder = SQLBuilder.GetSQLBuilder(2);
Console.WriteLine(_builder.Build());
_builder = SQLBuilder.GetSQLBuilder(3);
Console.WriteLine(_builder.Build());
Console.ReadKey();
}
public List<Product> GetByStateToList(int ConditionState)
{
string _queryStr = string.Empty;
var _queryResult = QueryDatabase(_queryStr);
return _queryResult;
}
public List<Product> QueryDatabase(string queryStr)
{
// .....查询处理
return new List<Product>();
}
}
}结果:
