MRFerocius
MRFerocius

Reputation: 5629

How to set a property value from an expression?

I need orientation on this scenario. For example I have this class:

public class Schema
{
   public string Value {get; set;}
}

On the front end the user will have the chance to enter the value for that property:

Schema.Value = [Expression here]

Now the user can call a function that returns a string, or he can concatenate Values from different schemas to assign the value to that particular schema value property.

How is the best way to do it? I find this difficult to explain, but how do I save that expression (the mechanism) and then calculate it during runtime?

Thanks in advance guys!

Upvotes: 1

Views: 254

Answers (1)

dan radu
dan radu

Reputation: 2782

You can use the CodeDomProvider class to evaluate expressions at runtime, or script engines like CS-Script. Here is a simple test which evaluates a DateTime expression:

[TestMethod]
public void ExecuteTest()
{
    CodeDomProvider provider = provider = CodeDomProvider.CreateProvider("CSharp");
    CompilerParameters cp = new CompilerParameters();
    cp.GenerateExecutable = false;
    cp.GenerateInMemory = true;
    cp.TreatWarningsAsErrors = false;
    string source = @"using System; namespace N { public class C { public static DateTime Execute() { return DateTime.Now.AddDays(10); } } }";
    CompilerResults cr = provider.CompileAssemblyFromSource(cp, source);
    if(cr.Errors.Count > 0)
    {
        foreach(CompilerError ce in cr.Errors)
        {
            Console.Out.WriteLine("  {0}", ce.ToString());
        }
        Assert.Fail("Compilation error(s).");
    }
    else
    {
        object obj = cr.CompiledAssembly.CreateInstance("N.C");
        MethodInfo mi = obj.GetType().GetMethod("Execute", BindingFlags.Public | BindingFlags.Static);
        var actual = (DateTime)mi.Invoke(obj, null);
        Assert.IsNotNull(actual);
        var expected = DateTime.Now.AddDays(10).Date;
        Assert.AreEqual(expected, actual.Date);
    }
}

This code requires reflection to discover the C class and Execute method. You will need to import System.Reflection and System.CodeDom.Compiler namespaces.

You have to be careful what classes / methods you expose in the expressions, because it can be a big security issue. You can add your own classes, add references from external assemblies, etc. and you don't have control on what is being executed.

Upvotes: 1

Related Questions