Requirement Description: There are four input boxes on a page, and each input box is bound with a verification rule. User input must be verified based on each input rule after the user input is complete. These verification rules can be dynamically modified in the background. As shown in: the original idea is to use regular expressions for implementation. In the background database, you only need to store the regular expression for verification. When verification is required, obtain the corresponding regular expression from the backend database. The idea is good, that is, there is a problem when it comes to implementation. For example, the first requirement in is complicated if you use a regular expression. You have checked some information on the Internet and have not found a general regular expression that can detect the number range. The most terrible thing is that the first one above can be changed. If the user suddenly changes to:> 34.5 & <999999.9 on which day, how should I write this regular expression? Currently, no regular expression is found for verifying the number range. So this is not feasible. However, it is certain that the validation rules are extracted to the database for configuration, but a valid and simple expression is missing. Expression, expression... suddenly think that lambda expressions are not a kind of expressions. It would be much simpler if we asked him to make a range-like judgment. For example, if you want to perform the above range judgment, you can write it as: o => o> 100 & o <499, which is less advanced than the regular expression. Now we need to consider how to let the background code extract this lambda expression from the database and successfully execute the returned results. Naturally, the term dynamic compilation can be implemented and returned as long as these code snippets can be dynamically compiled. The initial idea of dynamically compiling c # code is as follows: verify whether it is feasible. Google has a dynamic compilation of c # code, search for this article http://www.cnblogs.com/jailu/archive/2007/07/22/827058.html in the garden. Thank you for the detailed tutorial. The Code provided by the author obviously cannot be directly used here. The interface we need should be such a bool Validate (string lambda, string userInput); the first parameter is the lambda expression string retrieved from the database, the second parameter is the value entered by the user for verification.
Static bool validateInput (string lambda, string input) {// 1. CSharpCodePrivoder CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider (new Dictionary <string, string> () {"CompilerVersion", "v3.5"}); // 2. ICodeComplier ICodeCompiler objICodeCompiler = objCSharpCodePrivoder. createCompiler (); // 3. compilerParameters objCompilerParameters = new CompilerParameters (); objCompilerParameters. referencedAssemblies. add ("System. dll "); objCompilerParameters. referencedAssemblies. add ("System. core. dll "); objCompilerParameters. referencedAssemblies. add ("System. xml. linq. dll "); objCompilerParameters. generateExecutable = false; objCompilerParameters. generateInMemory = false; // 4. compilerResults cr = objICodeCompiler. compileAssemblyFromSource (objCompilerParameters, GenerateCode (lambda, input); if (cr. errors. hasErrors) {Console. writeLine ("Compilation error:"); foreach (CompilerError err in cr. errors) {Console. writeLine (err. errorText) ;}} else {Assembly objAssembly = cr. compiledAssembly; object objHelloWorld = objAssembly. createInstance ("DynamicCodeGenerate. dynamicValidate "); MethodInfo objMI = objHelloWorld. getType (). getMethod ("Validate"); return (bool) objMI. invoke (objHelloWorld, null);} return false ;}
You can use the CompileAssemblyFromSource method to dynamically compile the code. Because lambda expressions are required, the compiler version 3.5 is specified when CSharpCodeProvider is created. After compilation, you can call the corresponding dynamic compilation method through reflection. In this example, we need to pay attention to how to construct a code snippet that can execute lambda expressions.
static string GenerateCode(string lambda, string input) { StringBuilder sb = new StringBuilder(); sb.Append("using System;"); sb.Append(Environment.NewLine); sb.Append(Environment.NewLine); sb.Append("namespace DynamicCodeGenerate"); sb.Append(Environment.NewLine); sb.Append("{"); sb.Append(Environment.NewLine); sb.Append(" public class DynamicValidate"); sb.Append(Environment.NewLine); sb.Append(" {"); sb.Append(Environment.NewLine); sb.Append(" public delegate TResult Func<T, TResult>(T arg);"); sb.Append(Environment.NewLine); sb.Append(" public bool Validates(Func<string, bool> f)"); sb.Append(Environment.NewLine); sb.Append(" {"); sb.Append(Environment.NewLine); sb.Append(" return f(\"" + input + "\");"); sb.Append(Environment.NewLine); sb.Append(" }"); sb.Append(Environment.NewLine); sb.Append(" public bool Validate()"); sb.Append(Environment.NewLine); sb.Append(" {"); sb.Append(Environment.NewLine); sb.Append(" return Validates(" + lambda + ");"); sb.Append(Environment.NewLine); sb.Append(" }"); sb.Append(Environment.NewLine); sb.Append(" }"); sb.Append(Environment.NewLine); sb.Append("}"); string code = sb.ToString(); Console.WriteLine(code); Console.WriteLine(); return code; }
As you can see, I declare a Validates method, which accepts a delegate Func. The input is a string and the return value is bool. Then declare a Vlidate and call the Validates method and pass in lambda. In this way, we can dynamically compile and execute the specified lambda expression. Efficiency
This Code uses both dynamic compilation and reflection efficiency. However, flexibility and efficiency have always been difficult. If you have other better methods, please feel free to give me some advice!