在.Net中反射执行代码
您如何反思性地或动态地在.Net中执行代码?如果XML包含内在的东西“[]”我要处理的文本而不是文字而是代码:在.Net中反射执行代码
<Name>DateZero</Name>
<Value>DateTime.Now.AddDays(-2)</Value>
<Name>DateOne</Name>
<Value>[DateTime.Now.AddDays(-1).ToString("MM/dd/yy")]</Value>
<Name>DateTwo</Name>
<Value>[DateTime.Now.ToString("MM/dd/yy")]</Value>
意味着对于DateZero值将呈现为“DateTime.Now.AddDays(-2 )“,但对于接下来的两个,它将呈现为06/10/09和06/11/09。
CS-Script会做你想要的。
从自己的一个例子:
Assembly assembly = CSScript.LoadMethod(
@"public static void PrintSum(int a, int b)
{
Console.WriteLine((a+b));
}");
AsmHelper script = new AsmHelper(assembly);
script.Invoke("*.PrintSum", 1, 2);
这应该是很容易做你想要什么。我将它用于我们的规则引擎(刚刚从Boo切换),对于动态代码非常有用。
您是否会更好地定义一组可能的常量,然后您可以在代码中对其进行解析并动态执行,而不仅仅是通过任何C#代码。
它看起来像你需要某种基本的规则处理器。有几个选项可以完成你所需要的。像Randolpho提到的那样,您可以使用Reflection.Emit在运行时生成轻量级IL代码。另一种选择是,如果你有.NET 3.5,则使用表达式树。
随着LINQ的推出,微软需要在.NET中添加一个基本的表达式引擎,以便在编译过程中可以将LINQ语句转换为。然而,表达式库不仅限于支持LINQ,而且您应该能够编写一个基本的分析器,将您的XML转换为表达式树。每个表达式树可以稍后编译成一个委托,然后可以同步或异步调用该委托。
你可能会发现,如果你做探索表达式树航线以下链接有用:
它提供了一个动态的表达式解析器,其中,虽然它不完全支持你在有表情你的问题,几乎支持任何其他基本表达。
你真的想让任何C#吗?
如果是这样,你可能想看看this script engine for C#。请记住,能够运行任意代码是一个巨大的安全风险。
如果您在等待.NET 4.0(现在测试版,今年晚些时候发布)时可以使用,那么您可以使用DLR或动态语言运行库来实现此目的。另一方面,如果你不想依赖.NET 4.0,并且你愿意限制自己,那么你可以很简单地使用Reflection。 如果你可以限制自己,例如,在DateTime实例上的方法,事情会更简单。此示例显示如何通过反射调用一个设置为NOW的DateTime实例。
DateTime d = DateTime.Now;
string logicToInvoke= "Now.AddDays(12)";
string pattern = @"^Now\.(?<methodname>\w+)\((?<argstring>[^\)]*)\)";
RGX.Match match = RGX.Regex.Match(logicToInvoke, pattern);
// If match not found, logic is improperly formed.
if (!match.Success)
{
Console.WriteLine("The DateTime method logic is improperly formed.");
return;
}
// Store method and arg
string methodName = (string) match.Groups["methodname"].Value;
string argString = (string) match.Groups["argstring"].Value;
Console.WriteLine("Invoking method '{0}' with args '{1}'...", methodName, argString);
System.Type t= d.GetType();
try
{
switch (methodName)
{
case "AddDays" :
int daysToAdd = System.Int32.Parse(argString);
DateTime result = (DateTime) t.InvokeMember (methodName,
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.InvokeMethod ,
null, d, new object [] {daysToAdd});
Console.WriteLine("Result: {0}", result.ToString("yyyy/MM/dd"));
break;
default:
Console.WriteLine("unsupported method: {0}", methodName);
break;
}
}
catch (System.Exception exc1)
{
Console.WriteLine("Exception while invoking method: {0}", exc1);
}
我建议保持DateTime值的格式与它的值分开。的时间(“YY/MM/DD”)的格式可能在属性中更好的指定,与:
<Name>DateOne</Name>
<Value format="MM/dd/yy">[Now.AddDays(-1)]</Value>
取决于你想要做什么,你可能会发现,从春季.NET一些组件是有用的。看看Spring .NET Expressions。
例如:
(DateTime) ExpressionEvaluator.GetValue(null, "new DateTime(1974, 8, 24)")
,其中 “新的DateTime(1974,8,24)” 是你的文字
如果您不需要C#语法到最后一个逗号,最简单的这样做的方式可能是通过使用像IronPython这样的DLR语言。谷歌为“托管蟒蛇”,你会发现样本。
你真的想允许任何C#代码吗?看起来像一个巨大的安全漏洞。 – Cheeso 2009-06-11 16:03:49