有一种简单的方法可以将(lambda表达式)字符串解析为Action委托吗?

我有一个方法,根据传递给它的动作委托改变“帐户”对象:

public static void AlterAccount(string AccountID, Action AccountAction) { Account someAccount = accountRepository.GetAccount(AccountID); AccountAction.Invoke(someAccount); someAccount.Save(); } 

这按预期工作……

 AlterAccount("Account1234", a => a.Enabled = false); 

…但是现在我想尝试做的是这样的方法:

 public static void AlterAccount(string AccountID, string AccountActionText) { Account someAccount = accountRepository.GetAccount(AccountID); Action AccountAction = MagicLibrary.ConvertMagically<Action>(AccountActionText); AccountAction.Invoke(someAccount); someAccount.Save(); } 

它可以像以下一样使用:

 AlterAccount("Account1234", "a => a.Enabled = false"); 

禁用帐户“Account1234”。

我已经看过linq动态查询库 ,它似乎或多或少地做了我想要的但是对于Func类型的委托,我对表达式树等的了解还不够好,无法弄清楚如何实现我的目标想。

有没有一种简单的方法可以做我想要的,或者我是否需要正确学习表达式并编写大量代码?

(我想这样做的原因是允许从powershell脚本中批量更新帐户对象的简单方法,其中用户可以指定lambda表达式来执行更改。)

动态LINQ库是一个很好的选择,因为它将生成表达式,您可以轻松地编译为代码。

您提供的示例实际上会生成一个布尔值 – 因此您应该能够请求Func并且可能会将其排序。

编辑:这当然是错误的,因为表达式根本没有赋值。

所以,另一种可能的方法是采取两个lambdas。 一个找到你想要的属性,一个提供一个值:

(a => a.AccountId),(a => true)

然后使用reflection将第一个lambda中引用的属性设置为第二个lambda的结果。 Hackish,但与调用C#编译器相比,它仍然可能是轻量级的。

这样你就不必自己做很多代码 – 你得到的表达式将包含你需要的大部分内容。

您可以尝试这样: 使用隔离的AppDomain的动态Lambda表达式

它使用CodeDOM编译器编译lambda表达式。 为了处理创建的内存中程序集,编译器在一个独立的AppDomain上运行。 对于通过域边界传递表达式,必须将其序列化。 唉, Expression<>不是可Serializable 。 因此,必须使用一个技巧。 所有细节都在post中解释。

顺便说一下,我是那个组件的作者。 我非常希望听到您的反馈意见。

没有通用的方法可以在没有完整编译的情况下将字符串解析为lambda表达式,因为lambda表达式可以引用在lambda表达式之外定义的内容。 我知道没有库可以处理你想要的特定情况。 在C#讨论组的一个post上对此进行了长时间的讨论。

获得所需内容的最简单方法是在运行时编译方法。 你可以写一个函数,它接受字符串“a.Enabled = true; return a;” 并坚持在一个以帐户作为参数的函数中间。 我会使用这个库作为起点,但你也可以使用另一个线程中提到的函数。

这很简单:

  • 使用CodeDom生成包含您将用于构建表达式的“周围类”的模块; 此类必须实现应用程序已知的接口
  • 使用CodeSnippedExpression将表达式注入其成员。
  • 使用Activator类型在运行时创建此类的实例。

基本上,您需要使用CodeDom构建以下类:

 using System; using MyNamespace1; using ... using MyNamespace[N]; namespace MyNamespace.GeneratedTypes { public class ExpressionContainer[M] : IHasAccountAction { public Action AccountAction { get { return [CodeSnippedExpression must be used here]; } } } } 

假设IHasAccountAction是:

 public IHasAccountAction { public Action AccountAction { get; } } 

如果这样做,您可以轻松地从字符串中获取编译的表达式。 如果需要表达式树表示,请在生成的类型中使用Expression>而不是Action

您可以使用Spring.NET的lambda表达式评估引擎

表达式可能略有不同,但仍然会使用String表达式。