Executing code from a text field on the fly

I have a service that has many different methods with many parameters. I created a service client, but it would be painful to create an interface for all possible parameters and functions, so I only have one button for each method, and the code sets up all the parameters. It works well, but every time you need a different parameter, you need to change the code. Therefore, I thought that if I had a text box with code that would compile and be called on the fly, that would be very convenient to use. So I want to have a text box with code like ExecuteOperation1("a", "b", "c") , where ExecuteOperation is defined in my form class. And then I can easily change the settings on the fly. I tried to find how this can be done, but all the examples show compilation with namespaces and classes and so on. Is there a way to somehow run the dynamic code inside your class. Of course, other simple solutions to my problem are also evaluated.

+4
source share
2 answers

There are several different ways to run code on the fly. One good way is to use the Microsoft-provided dynamic.cs file, available here (in LinqSamples \ DynamicQuery \ DynamicQuery). Usage example here .

You can also build expression trees yourself for this article on MSDN . But for this you need to write a parsing code.

I used both of the above, and I think the first approach seems the most promising for the problem you want to solve. For example, you can make some arbitrary object o parameter of your expression and include other objects, such as settings , so the user can write o.ExecuteOperation1("a", "b", "c", settings) , as in the test program below .

 using System.Linq.Expressions; using System.Linq.Dynamic; // ... public class Settings { public int x; } public class Window { public object ExecuteOperation1(string a, string b, string c, Settings s) { Console.WriteLine("{0}, {1}, {2}, {3}", a, b, c, sx); return true; } } class Program { static void Main(string[] args) { string strExpr = "o.ExecuteOperation1(\"a\", \"b\", \"c\", settings)"; Window form = new Window(); Settings s = new Settings(); sx = 42; Type retType = typeof(object); ParameterExpression[] paramExprs = new ParameterExpression[] { Expression.Parameter(typeof(Window), "o"), Expression.Parameter(typeof(Settings), "settings") }; LambdaExpression Le = System.Linq.Dynamic.DynamicExpression.ParseLambda( paramExprs, retType, strExpr); Delegate compiledLe = Le.Compile(); object result = compiledLe.DynamicInvoke(form, s); Console.WriteLine("Result is {0}", result.ToString()); } } 

This program displays

 a, b, c, 42 Result is True 

I had to comment on lines 1137 through 1138 in Dynamic.cs to get this to work (these lines preclude the use of a custom Window type).

Finally, there is Roslyn , which makes the .net compiler available as a service. I did not use it myself because it was in a technical preview, and I wanted something that I could deploy now. However, this seems to be a lot of examples, some of which focus on what you want.

+3
source

If it always looks like ExecuteOperation1("a", "b", "c") , then you can use reflection to determine the names of methods and parameters. For example, folloring code gives you a list of methods. MethodInfo.Invoke can be used to call methods.

 typeof(Service).GetMethods(BindingFlags.Public|BindingFlags.Instance); 

This approach is not very flexible, but relatively easy to understand and does not require additional libraries.

0
source

Source: https://habr.com/ru/post/1487251/


All Articles