2013-06-20 4 views
4

У меня есть служба, которая имеет множество разных методов с множеством параметров. Я создал клиент службы, но было бы больно создавать интерфейс для всех возможных параметров и функций, поэтому у меня есть только одна кнопка для каждого метода, а код настраивает все параметры. Он работает хорошо, но каждый раз, когда вам нужен другой параметр, вам нужно изменить код. Поэтому я подумал, что если бы у меня было текстовое поле с кодом, который будет компилироваться и вызываться на лету, что было бы очень удобно использовать. Поэтому я хочу, чтобы у меня есть текстовое поле с кодом ExecuteOperation1("a", "b", "c"), где ExecuteOperation определен в моем классе формы. И тогда я могу легко менять параметры на лету. Я попытался найти, как это можно сделать, но все примеры показывают компиляцию с пространствами имен и классами и так далее. Есть ли способ как-то запустить динамический код внутри вашего класса. Разумеется, оцениваются и другие простые решения для моей проблемы.Выполнение кода из текстового поля «на лету»

+0

Вы уверены, что это [тег: генерация кода] вместо [tag: reflection]? –

+0

Проверьте эту ссылку http://www.codeproject.com/Articles/12499/Run-Time-Code-Generation-I-Compile-C-Code-using-Mi – Kurubaran

+0

@ J.A.I.L. Не совсем уверен, действительно, я не думаю, может быть, лучше вообще удалить тег. –

ответ

3

Существует несколько различных способов запуска кода на лету. Одним из приятных способов является использование предоставленного Microsoft файла dynamic.cs here (в LinqSamples \ DynamicQuery \ DynamicQuery). Примером использования является here.

Вы также можете сами построить деревья выражений вручную в соответствии с this article on MSDN. Но для этого вам нужно написать код разбора.

Я использовал оба вышеупомянутых, и я думаю, что первый подход кажется наиболее перспективным для проблемы, которую вы хотите решить. Например, вы можете сделать произвольный объект o параметром вашего выражения и включить в него другие объекты, например settings, поэтому пользователь может написать o.ExecuteOperation1("a", "b", "c", settings), как в приведенной ниже тестовой программе.

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, s.x); 
     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(); 
     s.x = 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()); 
    } 
} 

Эта программа выводит

a, b, c, 42 
Result is True 

мне пришлось закомментировать строки 1137 до 1138 в Dynamic.cs, чтобы получить эту работу (эти строки исключает использование определенного пользователем типа Window).

И, наконец, есть Roslyn, что делает компилятор .net доступным как услугу. Я не использовал это сам, потому что это в техническом предпросмотре, и я хотел, чтобы я мог развернуть его сейчас. Тем не менее, похоже, у вас много примеров, некоторые из которых ориентированы на то, что вы хотите.

+0

Спасибо за ответ. Мои параметры - это действительно объекты, которые я должен заполнить, и перейти к методу.Поэтому вместо строки «a» это должны быть параметры var = new. Настройки {\ * здесь установлены * *}, которые затем передаются методу. Можно ли писать и в выражении? –

+0

Думаю, вам нужно поиграть с ним, чтобы посмотреть, что вы можете сделать. Я бы, вероятно, определил объекты настроек в отдельной части вашей формы, а затем дайте пользователю указать его (их) как часть строки, в которую они вписываются. Я изменил свой ответ, чтобы показать это. – TooTone

+0

Самая важная часть - иметь этот код настроек из текстового поля, поэтому это не будет работать, как в вашем примере. Но я постараюсь понять, могу ли я изменить его, чтобы делать то, что хочу. Возможно, мы можем сделать один и тот же трюк с настройками и вернуть их как отдельное выражение, но все, что сделало бы эту вещь довольно сложной, и я хотел иметь только одно текстовое поле со всем кодом для операции: создание параметров объекта, вызов метода с этими параметрами , –

0

Если оно всегда выглядит как ExecuteOperation1("a", "b", "c"), то вы можете использовать отражение для определения имен методов и параметров. Например, код folloring дает вам список методов. MethodInfo.Invoke может использоваться для вызова методов.

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

Это подход не очень гибкий, но относительно прост для понимания и не требует дополнительных библиотек.

+0

Это не совсем «а», «b», «c», это было просто упрощение, чтобы не вдаваться в подробности. У меня есть несколько сложных параметров объекта, которые я передаю, поэтому я не уверен, что это можно будет использовать. Самая интересная часть для меня - правильно заполнить свойства этих объектов –

Смежные вопросы