Это, конечно, возможно. Класс CodeSnippetCompileUnit делает в основном это.
Я написал вам пример кода использования. Вам нужно будет включить эти пространства имен:
- System.CodeDom.Compiler;
- System.CodeDom;
- Microsoft.CSharp;
- System.Reflection;
Вот код:
string source = @"
class MyType
{
public static int Evaluate(<!parameters!>)
{
return <!expression!>;
}
}
";
string parameters = "int a, int b, int c";
string expression = "a + b * c";
string finalSource = source.Replace("<!parameters!>", parameters).Replace("<!expression!>", expression);
CodeSnippetCompileUnit compileUnit = new CodeSnippetCompileUnit(finalSource);
CodeDomProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
CompilerResults results = provider.CompileAssemblyFromDom(parameters, compileUnit);
Type type = results.CompiledAssembly.GetType("MyType");
MethodInfo method = type.GetMethod("Evaluate");
// The first parameter is the instance to invoke the method on. Because our Evaluate method is static, we pass null.
int result = (int)method.Invoke(null, new object[] { 4, -3, 2 });
Замените "параметры" и "выражение" на что угодно, и вы получите общий оценщик выражений.
Если вы получили FileNotFoundException в results.CompiledAssembly, фрагмент не смог скомпилироваться.
Возможно, вы также захотите взглянуть на класс System.CodeDom.CodeSnippetExpression. Он используется для более точного чтения выражений, но само по себе выражение не может быть скомпилировано, поэтому вам нужно будет использовать больше CodeDom для создания рабочего класса и метода вокруг него. Это полезно, если вы хотите иметь возможность программно управлять типом создаваемого вами класса. CodeSnippetCompileUnit удобен для генерации всего рабочего класса сразу (и проще для примера), но для манипулирования им вам придется выполнять неудобные манипуляции со строками.