There are many algorithms to evaluate expressions, for example:
Is there any way to evaluate any mathematical expression using C# .net reflection or other modern .net technology?
There are many algorithms to evaluate expressions, for example:
Is there any way to evaluate any mathematical expression using C# .net reflection or other modern .net technology?
You can use Math-Expression-Evaluator library which implements Shunting Yard algorithm that I am author of. It supports simple expressions such as 2.5+5.9, 17.89-2.47+7.16, 5/2/2+1.5*3+4.58, expressions with parentheses (((9-6/2)*2-4)/2-6-1)/(2+24/(2+4)) and expressions with variables:
var a = 6;
var b = 4.32m;
var c = 24.15m;
var engine = new ExpressionEvaluator();
engine.Evaluate("(((9-a/2)*2-b)/2-a-1)/(2+c/(2+4))", new { a, b, c});
You can also pass parameters as named variables:
dynamic dynamicEngine = new ExpressionEvaluator();
var a = 6;
var b = 4.5m;
var c = 2.6m;
dynamicEngine.Evaluate("(c+b)*a", a: 6, b: 4.5, c: 2.6);
It supports .Net Standard 2.0 so can be used from .Net Core as well as .Net Full Framework projects and it doesn't have any external dependencies.
To dynamically compile code using the new Roslyn API's, and load the assembly in a .net core project;
string finalSource = ...;
IEnumerable<Assembly> references = ...;
var compilation = CSharpCompilation.Create("Dynamic",
new[] {
SyntaxFactory.ParseSyntaxTree(
finalSource,
CSharpParseOptions.Default
.WithLanguageVersion(LanguageVersion.Latest)
) },
references.Select(a => MetadataReference.CreateFromFile(a.Location)),
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default)
);
using var ms = new MemoryStream();
var e = compilation.Emit(ms);
if (!e.Success)
throw new Exception("Compilation failed");
ms.Seek(0, SeekOrigin.Begin);
var context = new AssemblyLoadContext(null, true);
var assembly = context.LoadFromStream(ms);
Note that along with any other types required by the source you are compiling. In order to load the compiled assembly within the same process, references will need to include;
AppDomain.CurrentDomain.GetAssemblies().Where(a => a.GetName().Name == "netstandard").Single(),
typeof(object).Assembly