【问题标题】:Use LINQ expression to Update Property of object使用 LINQ 表达式更新对象的属性
【发布时间】:2013-09-06 21:53:05
【问题描述】:

所以我有一种情况,我需要根据包含的值动态更新对象的属性。在下面的情况下,如果条件为真,我需要用不同的字符串替换当前值的前两个字符来更新值。

PersonDetail.EvaluateConditionalRule("ID", 
                    "((ID.Length > Convert.ToInt32(@0) ) AND ID.Substring(Convert.ToInt32(@1), Convert.ToInt32(@2)) == @3 )",
                     new[] { "1", "0", "2", "SS" }, " ID = (@0  + ID.Substring(Convert.ToInt32(@1))) " , new[] { "98", "2" });


   public static void EvaluateConditionalRule(this PersonDetail  Detail, String PropertyToEvaluate,
            String ConditionalExpression, String[] parameters, String IfTrueExpression,String[] IfTrueExpreassionparameters  )
          {
               var property =  Detail.GetType().GetProperties().Where(x => x.Name == PropertyToEvaluate).FirstOrDefault();
               if (property == null)
                    throw new InvalidDataException(String.Format("Please specify a valid {0} property name for the evaluation.",  Detail.GetType()));
               //put together the condition like so 

               if (new[] {  Detail }.AsQueryable().Where(ConditionalExpression, parameters).Count() > 0 && IfTrueExpression != null)
               {
                    var result = new[] {  Detail }.AsQueryable().Select(IfTrueExpression, IfTrueExpreassionparameters);

                  //Stuck Here as result does not contain expected value 

                    property.SetValue( Detail,result , null);
               }
          }

基本上我想要的是,能够执行馈送此的表达式,并且我认为我没有正确评估子字符串替换表达式的格式。我从上面想要的是像

ID = "98"+  ID.Substring(2);

任何帮助将不胜感激。谢谢

【问题讨论】:

  • 也许这可以帮助你:C# 中的谓词代表 stackoverflow.com/questions/556425/…
  • 是否必须在字符串而不是 Lambda 表达式中有条件?
  • 是的,这是必要的。就像我说的那样,我正在努力使它尽可能动态。

标签: c# linq lambda


【解决方案1】:

请向我们提供一些信息,说明您为何需要让更新变得如此动态。您希望用户手动输入条件字符串吗?

关于您的代码:

您的选择器字符串错误。在 LINQ 动态查询库中有一个特殊的语法。请在随示例提供的文档中查找(参见段落表达式语言和数据对象初始化器):http://msdn.microsoft.com/en-US/vstudio/bb894665.aspx

我写了一个小样本:

var id = new string[] { "SS41231" }.AsQueryable();

// *it* represents the current element
var res = id.Where("it.Length > @0 AND it.Substring(@1, @2) = @3", 1, 0, 2, "SS"); // Save the result, don't throw it away.

if (res.Any())
{
    // Line below in normal LINQ: string newID = res.Select(x => "98" + x.Substring(2)).First();
    string newId = res.Select("@0 + it.Substring(@1)", "98", 2).Cast<string>().First();

    Console.WriteLine(newId);
}

请写一些反馈。

您好。

【讨论】:

    【解决方案2】:

    不确定您所说的“动态”到底是什么意思,但我认为使用 lambdas 的方法不适合您:

    static void Main(string[] args) {
            User user = new User { ID = 5, Name = "Test" };
            SetNewValue(user, u => u.Name, s => s.StartsWith("T"), s => s + "123");
        }
    
        static void SetNewValue<TObject, TProperty>(TObject obj, Func<TObject, TProperty> propertyGetter, Func<TProperty, bool> condition, Func<TProperty, TProperty> modifier) {
            TProperty property = propertyGetter(obj);
            if (condition(property)) {
                TProperty newValue = modifier(property);
                //set via reflection
            }
        }
    

    所以我建议您使用Expression trees,它允许您构建您喜欢的任何运行时构造,作为您示例的一部分

    var exp = Expression.Call(Expression.Constant("test"), typeof(string).GetMethod("Substring", new[] { typeof(int) }), Expression.Constant(2));            
    Console.WriteLine(Expression.Lambda(exp).Compile().DynamicInvoke()); //prints "st"
    

    但是,如果您想使用带有原始 c# 代码的字符串作为表达式,请检查 CSharpCodeProvider

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多