C # Dynamic compilation and implementation of dynamic configuration of button functions

Source: Internet
Author: User
Tags foreach bool eval execution expression parse string reflection throw exception

Now to do the system requirements to be more and more flexible, more convenient function configuration, sacrificing a small part of the efficiency, and in exchange for the flexibility of the system, for maintenance, function extension upgrades and other work to provide a great convenience.

Two days ago, a project requires that the buttons on the interface be configurable, and that the location and function are configurable. The location is good, you can use XML. But the ability to configure is a bit difficult. If you use an interface, then the parameters are not set, and even with the interface, you have to explicitly instantiate which class when the actual call is made. You might also say that with reflection, well, that's a good idea, but when you call, the parameters are uncertain and the reflection is useless. After a long search, the final choice is dynamic compilation.

Complete the process of dynamic compilation with a specialized class. In fact, this dynamic compilation, is dynamically generated code, after dynamic compilation, and then directly in the system can be used. So you need to add the dynamic link libraries, assemblies, and namespaces that you need in your code to function. The following are the dynamically compiled classes I used:

Using System;  
Using System.Data;  
Using System.Configuration;  
Using System.IO;  
Using System.Text;  
Using System.CodeDom.Compiler;  
Using System.Windows.Forms;  
Using Microsoft.csharp;  
      
Using System.Reflection;  
    namespace Dynamicaddfunction {///<summary>///This class is used to convert a string to executable text and execute it to dynamically define the event that the button responds to. </summary> public class Evaluator {private string filepath = Path.Combine (application.  
          
        StartupPath, "Funbtn.config"); Constructors for #region Constructors///<summary>///executable strings///</summary>///& Lt;param name= "Items" >///executable string array///</param> public evaluator (Evaluato      Ritem[] items) {constructevaluator (items); Invoke parse string constructors for parsing}///<summary>///executable string Constructors///</summary&gt     
        ; <param name= "ReturntypE "> Return value type </param>///<param name=" expression "> execution expression </param>///<param n  
        Ame= "Name" > execution string name </param> public evaluator (Type returntype, string expression, string name)  {///create executable string array evaluatoritem[] items = {New Evaluatoritem (returntype, expression, name)  
            };      Constructevaluator (items);     
        Invoke parse string constructors for parsing}///<summary>///executable string Constructors///</summary>  
        <param name= "Item" > Executable string Entry </param> public evaluator (Evaluatoritem item)      {evaluatoritem[] items = {Item};//convert an executable string entry to an array of executable string items constructevaluator (items); Invoke parse string constructors for parsing}///<summary>///parsing string Constructors///</summary&gt     
        ; <param name= "Items" > unresolved string array </param> private void ConStructevaluator (evaluatoritem[] items) {//create C # compiler instance//icodecompiler comp = (new CSharpCodeProvider ().  
            CreateCompiler ());   
            CSharpCodeProvider comp = new CSharpCodeProvider ();  
      
            The compiler's incoming parameter compilerparameters CP = new CompilerParameters ();  
            Configer Configer = configer.current (filepath); string[] Assemblies = Configer.  
            getassembly ("Funbtn//assembly//dll", "name"); Cp.           Referencedassemblies.addrange (assemblies); Adds an assembly collection//CP.              Referencedassemblies.add ("System.dll"); Add the reference//CP for the assembly System.dll.         Referencedassemblies.add ("System.Data.dll"); Add the reference//CP for the assembly System.Data.dll.          Referencedassemblies.add ("System.Xml.dll"); Add the reference//CP for the assembly System.Xml.dll.  
            Referencedassemblies.add ("System.Windows.Forms.dll"); Cp.  
Referencedassemblies.add ("FunButton.dll");            Cp.  
            Referencedassemblies.add ("DynamicAddFunction.exe"); Cp.                          GenerateExecutable = false; Does not generate the executable CP.                             GenerateInMemory = true;               Run StringBuilder code = new StringBuilder () in memory; Create a code String * * Add a common and necessary reference String *//Get the referenced namespace string[ ] Usings = Configer.  
      
            getassembly ("funbtn//assembly//using", "name"); foreach (Var @using in Usings) {code. Append (@using + "\ n");//Add referenced namespace}//code. Append ("Using System;  
            \ n "); Code. Append ("Using System.Data;  
            \ n "); Code. Append ("Using System.Data.SqlClient;  
            \ n "); Code. Append ("Using System.Data.OleDb;  
            \ n "); Code. Append ("Using System.Xml;  
            \ n "); Code. Append ("Using Funbutton;  
            \ n "); Code. Append("Using System.Windows.Forms;  
            \ n "); Code. Append ("Using Dynamicaddfunction;  
      
            \ n "); Code.                  Append ("namespace Evalguy {\ n"); The namespace of the generated code is Evalguy, as is code.          Append ("public class _evaluator {\ n");     
            Generates a _evaluator class in which all executable code runs foreach (Evaluatoritem item in items)//traverses each executable string entry {Code. AppendFormat ("public {0} {1} ()",///Add define common function code item. ReturnType.Name.ToLower (),//function return value is the return value type item defined in the executable string entry.                       Name); The function name is code for the execution string name defined in the executable string entry.                                  Append ("{"); Add function Start bracket if (item. Returntype.name = = "Void") {code. AppendFormat ("{0};", item. Expression);//Add function body, return value of expression defined in executable string entry} ElSE {code. AppendFormat ("Return ({0});", item. Expression);//Adds the function body, returns the value of the expression defined in the executable string entry} code.                                 Append ("}\n"); Add function End Bracket} code.                                 Append ("}}"); Add class end and Namespace end bracket//Get return result of compiler instance compilerresults CR = Comp. CompileAssemblyFromSource (CP, code.  
      
            ToString ()); if (CR. errors.haserrors)//If there is an error {StringBuilder error = new String          Builder (); The error message string is created.                Append ("Compile with Error expression:"); Add error text foreach (CompilerError err in CR. Errors)//traverse every occurrence of the compile error {errors. AppendFormat ("{0}\n", err.)     ErrorText); Add in error text, newline after each error throw new Exception ("Compile Error:" + error. ToString ();//Throw exception} Assembly a = cr.compiledassembly;     Gets the assembly _compiled = A.createinstance ("Evalguy._evaluator") of the compiler instance; Find and declare an instance of Evalguy._evaluator by Assembly #endregion #region Public member///<sum Mary>///Execute string and return integer value///</summary>///<param name= "name" > execution string name &  
        lt;/param>///<returns> Execution result </returns> public int evaluateint (string name)  
        {return (int) Evaluate (name); ///<summary>///Execute string and return string value///</summary>///<para M name= "name" > execution string name </param>///<returns> Execution result </returns> public string Eva  
        Luatestring (string name) {return (string) Evaluate (name); ///<summary>///Execution stringand returns the Boolean value///</summary>///<param name= "name" > execution string name </param>/// <returns> Execution result </returns> public bool Evaluatebool (string name) {return (  
        BOOL) Evaluate (name); ///<summary>///Execute string and return object value///</summary>///<  param name= "name" > execution string name </param>///<returns> Execution result </returns> public object Evaluate (string name) {MethodInfo mi = _compiled.gettype (). GetMethod (name),//Gets the reference to the method whose name is named in the _compiled type.                  Invoke (_compiled, NULL); Executing mi referenced method} public void Evaluatevoid (string name) {MethodInfo mi = _compiled.gettype (). GetMethod (name),//Gets the reference Mi of the method _compiled the name of the owning type.                  Invoke (_compiled, NULL); Perform the method referenced by Mi     
        #endregion #region Static member///<summary>///Execution table Reach and return integer value///</summary>///<param name= "code" > Expressions to execute </param>//  
            /<returns> results </returns> static public int Evaluatetointeger (string code) { Evaluator eval = new Evaluator (typeof (int), code, Staticmethodname);//Generate a pair of evaluator class return (int) E Val.                        Evaluate (Staticmethodname);     
        Executes and returns an integer data}///<summary>///executes an expression and returns a String value///</summary>     
        <param name= "code" > Expressions to execute </param>///<returns> op results </returns> static public string evaluatetostring (string code) {Evaluator Eval = new Evaluator (typeof (string), code, Staticmethodname);//Generate Evaluator Return (string) eval for the class.Evaluate (Staticmethodname);      
        Executes and returns the string data}///<summary>///executes an expression and returns a Boolean value///</summary>     
        <param name= "code" > Expressions to execute </param>///<returns> op results </returns> static public bool Evaluatetobool (string code) {Evaluator Eval = new Evaluator (typeof (Bo OL), code, STATICMETHODNAME)//Generate Evaluator class's pair like return (BOOL) eval.                       Evaluate (Staticmethodname); Executes and returns a Boolean data}///<summary>///executes an expression and returns an object value///</summar      
        y>///<param name= "code" > Expressions to execute </param>///<returns> op results </returns> Static public Object Evaluatetoobject (string code) {Evaluator Eval = new Evaluator ( typeof (object), code, Staticmethodname);//Generate a pair of evaluator class return EVAl.                             Evaluate (Staticmethodname); Executes and returns the object type data}///<summary>///executes an expression and returns a void null value/// </summary>///<param name= "code" > expression </param> static public void Evaluatet to execute ovoid (String code) {Evaluator Eval = new Evaluator (typeof (void), Code, Staticmethodname);//Generate Eva The Luator class is like Eval.                             Evaluatevoid (Staticmethodname);     
        Executes and returns the object type data} #endregion #region Private member///<summary> The execution string name of the static method///</summary> Private Const string staticmethodname = "Execut  
        Ebtncommand "; <summary>///is used to dynamically reference the generated class, execute its internal contained executable string///</summary> object _comp  
        iled = null; #endregion}///<summary>///executable string entry (that is, aExecutable string)///</summary> public class Evaluatoritem {///<summary>  
        return value type///</summary> public type returntype;  
        <summary>///executes an expression///</summary> public string Expression;  
        <summary>///Execution String name///</summary> public string name; <summary>///Executable String Item constructor///</summary>///<param name= " ReturnType "> Return value type </param>///<param name=" expression "> execution expression </param>///&l T;param name= "Name" > execution string name </param> public Evaluatoritem (Type returntype, string expression, string  
            Name) {returntype = ReturnType;  
            Expression = Expression;  
        name = name; }  
    }  
}

To improve its flexibility, the assembly and namespace added to the above class, as well as the code that invokes the functionality, are changed to read XML-formatted configuration files for retrieval. This can theoretically make it possible to add the functionality of any. NET-made DLL, EXE, etc. in the system. greatly enhance the flexibility of the system.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.