【问题标题】:How to set properties and nested property's properties with expression如何使用表达式设置属性和嵌套属性的属性
【发布时间】:2012-06-07 20:57:02
【问题描述】:

我用谷歌搜索了问题并搜索了 SO。有很多解决方案(我发现的)都没有完成。请您帮我设置一个类的属性及其嵌套属性的属性,由lambda 选择,使用Reflection

public class Parent
{
    public class Child
    { 
        public int Id { get; set; }
    }

    public string Name { get; private set; }
    public int Number {get; private set; }
    public Child Nested { get; set; }

    public Parent()
    {
        Nested = new Child();
    }

    public Test Set<TValue>(Expression<Func<???> func, TValue value)
    {
        // find the property name from expression
        // set the property by value
        return this;
    }
}

在消费者方面,我希望能够:

Parent t = new Parent();
t.Set<int>(t => t.Number, 6)
 .set<string>(t => t.Name, "something")
 .Set<int>(t => t.Nested.Id, 25);

【问题讨论】:

  • 为什么要专门表达? t.Set("Number", 6)t.Set("Nested.Id", 25) 就足够了吗?这可能更容易,我可以想出一些有趣的方法来做到这一点。
  • 没关系。我可以找到成员的名字(他们之间的.(点))。你能建议你的解决方案吗?
  • 在我做之前...您不能简单地使用直接 C# 的原因是什么?即t.Number = 6; t.Name = "something"; t.Nested.Id = 25;
  • @MarcGravell 实际上我是 C# 新手。我正在学习、学习和学习。没错,我可以使用t.Name = "";但是对于具有许多属性(和嵌套属性)的大类来说,这似乎并不容易。所以我认为如果我可以使用我在 Q 中所说的东西,它会更容易。提前致谢
  • 为什么更容易?为什么这样更好?了解我们想要实现的目标始终是最重要的

标签: c# reflection lambda expression-trees


【解决方案1】:

这样的事情应该可以工作:

public class Parent
{
    public Parent Set<TValue>(Expression<Func<Parent, TValue>> func, TValue value)
    {
        MemberExpression mex = func.Body as MemberExpression;
        if(mex == null) throw new ArgumentException();

        var pi = mex.Member as PropertyInfo;
        if(pi == null) throw new ArgumentException();

        object target = GetTarget(mex.Expression);
        pi.SetValue(target, value, null);
        return this;
    }

    private object GetTarget(Expression expr)
    {
        switch (expr.NodeType)
        {
            case ExpressionType.Parameter:
                return this;
            case ExpressionType.MemberAccess:
                MemberExpression mex = (MemberExpression)expr;
                PropertyInfo pi = mex.Member as PropertyInfo;
                if(pi == null) throw new ArgumentException();
                object target = GetTarget(mex.Expression);
                return pi.GetValue(target, null);
            default:
                throw new InvalidOperationException();
        }
    }
}

【讨论】:

  • 我要设置属性。不仅仅是签名
  • 谢谢,这是否也设置了嵌套属性值?我来测试一下
  • 而且...seeters 是 private。这样可以吗?
  • @king.net - 是的,它适用于嵌套属性,并且应该与私有设置器一起使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多