使用LINQ表达式更新对象的属性

时间:2013-09-06 21:53:05

标签: c# linq lambda

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

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);

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

2 个答案:

答案 0 :(得分:0)

不确定你的意思是什么意思“动态”但我认为使用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

答案 1 :(得分:0)

请向我们提供一些有关您为何需要更新此动态的信息。您是否希望用户手动输入条件字符串?

关于您的代码:

您的选择器字符串错误。在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);
}

请写一些反馈。

问候。

相关问题