- 问题描述
今天遇到一个棘手问题,要排查出某个项目代码中,所有Const单元中,所有常量定义和值,如下图所示:
首先想到两个方案:①直接按行读取源代码,检查 public const 后面的字符串进行代码行(以分号结尾为一行代码)分割处理。
②采用“正则表达式”,分别匹配到“ct_”、“【SQL语句】”常量定义。
两种方法其实大同小异,理论上可行,但是实际情况,开发人员“编码尚不规范”,给排查算法增添几分复杂度。比方说,SQL常量可能会换行、SQL常量还可能会拼接、有些常量中就会存在代码结束符(;)等等问题。
- 代码样列
期间忽略千辛万苦的技术探索,我们终于发现了一种方案:采用动态加载类+反射解析的方式。
public static void Main(string[] args)
{
// 1.CSharpCodePrivoder
CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider();
// 2.ICodeComplier
ICodeCompiler objICodeCompiler = objCSharpCodePrivoder.CreateCompiler();
// 3.CompilerParameters
CompilerParameters objCompilerParameters = new CompilerParameters();
objCompilerParameters.ReferencedAssemblies.Add("System.dll");
objCompilerParameters.GenerateExecutable = false;
objCompilerParameters.GenerateInMemory = true;
// 4.CompilerResults
string l_strText = File.ReadAllText(@"D:\我的文档\SharpDevelop Projects\fff\Const.cs");
CompilerResults cr = objICodeCompiler.CompileAssemblyFromSource(objCompilerParameters,l_strText);
if(cr.Errors.HasErrors)
{
Console.WriteLine("编译错误:");
foreach (CompilerError err in cr.Errors)
{
Console.WriteLine(err.ErrorText);
}
}
else
{
//5、CompiledAssembly
Assembly objAssembly = cr.CompiledAssembly;
Type t = objAssembly.GetType("Wesun.SW.M2012.Presentation.F201206.Const");
FieldInfo[] fis=t.GetFields(); // 注意,这里不能有任何选项,否则将无法获取到const常量
foreach (var fieldInfo in fis)
{
Console.WriteLine(fieldInfo.Name + "=" + fieldInfo.GetRawConstantValue().ToString());
}
}
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
public static class Const
{
public const string ct_StrPackMode ="select * from T200_product_pack_mode where (1=1) and product_no = ";
public const string ct_FetchCustomer = "select * from V201_sale_order_receiver_F201208 where (1=1)";
public const string ct_FetchProductProduceLine = "select * from TA05_product_produce_product where product_no={0} and sys_no = {1} and default_tag = 'T'" ;
public const string ct_fetchSimpleCode="select '' as request_field4 ,'' as request_field4_name_cn union all Select simple_no as request_field4, simple_name_cn as request_field4_name_cn "
+"From T200_simple_code where (1=1) AND (simple_type= 'RF4');";
public const string ct_FetchRequestField = "select * from V200_product_code_default where (1=1) ";
}
- 运行效果