C# 如何从表达式中设置属性值?
我需要了解这个场景。例如,我有一门课:C# 如何从表达式中设置属性值?,c#,dynamic,reflection,expression,C#,Dynamic,Reflection,Expression,我需要了解这个场景。例如,我有一门课: public class Schema { public string Value {get; set;} } 在前端,用户将有机会输入该属性的值: Schema.Value=[Expression here] 现在,用户可以调用返回字符串的函数,也可以连接来自不同模式的值,将值分配给特定的模式值属性 最好的方法是什么?我发现这很难解释,但如何保存该表达式(机制),然后在运行时进行计算 提前谢谢各位 您可以使用该类在运行时计算表达式,或编写类似的脚
public class Schema
{
public string Value {get; set;}
}
在前端,用户将有机会输入该属性的值:
Schema.Value=[Expression here]
现在,用户可以调用返回字符串的函数,也可以连接来自不同模式的值,将值分配给特定的模式值属性
最好的方法是什么?我发现这很难解释,但如何保存该表达式(机制),然后在运行时进行计算
提前谢谢各位 您可以使用该类在运行时计算表达式,或编写类似的脚本引擎。
下面是一个简单的测试,用于计算DateTime
表达式:
[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);
}
}
此代码需要反射来发现C
类和Execute
方法。您需要导入System.Reflection
和System.CodeDom.Compiler
名称空间
您必须小心在表达式中公开哪些类/方法,因为这可能是一个很大的安全问题。您可以添加自己的类,添加来自外部程序集的引用,等等,但您无法控制正在执行的操作。您可以使用该类在运行时计算表达式,或编写类似的脚本引擎。
下面是一个简单的测试,用于计算DateTime
表达式:
[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);
}
}
此代码需要反射来发现C
类和Execute
方法。您需要导入System.Reflection
和System.CodeDom.Compiler
名称空间
您必须小心在表达式中公开哪些类/方法,因为这可能是一个很大的安全问题。您可以添加您自己的类,从外部程序集添加引用等,并且您无法控制正在执行的内容。如果您根据用户定义的表达式在运行时这样做,那么考虑使用表达式计算器,或者如果您在基于用户定义表达式的运行时这样做,然后考虑使用类似于