代码之家  ›  专栏  ›  技术社区  ›  empi

强类型属性声明-此代码安全吗?

  •  2
  • empi  · 技术社区  · 15 年前

    我想知道下面的代码是否“安全”。所谓“安全”,我的意思是我不依赖于某些特定的编译器版本或未记录的特性。 我想获得具有属性/字段名称的字符串,但我想用强类型声明它(我希望编译器检查是否存在特定的字段/属性)。 我的方法是这样的:

    string GetPropertyName<T>(Expression<Func<T, object>> expression)
    {
        if (expression.Body is UnaryExpression)
        {
            var operand = ((UnaryExpression)expression.Body).Operand.ToString();
            return operand.Substring(operand.IndexOf(".") + 1);
        }
        else if (expression.Body is MemberExpression)
        {
            return ((MemberExpression)expression.Body).Member.Name;
        }
        else
        {
            throw new NotImplementedException();
        }            
    }
    

    下面是我想如何使用它:

    class Foo
    {
        public string A { get; set; }
        public Bar B { get; set; }
    }
    
    class Bar
    {
        public int C { get; set; }
        public Baz D { get; set; }
    }
    
    class Baz
    {
        public int E { get; set; }
    }
    
    
    GetPropertyName<Foo>(x => x.A)
    GetPropertyName<Foo>(x => x.B)
    GetPropertyName<Foo>(x => x.B.C)
    GetPropertyName<Foo>(foo => foo.B.D.E)
    

    提前谢谢你的帮助。

    3 回复  |  直到 15 年前
        1
  •  3
  •   LukeH    15 年前

    我不确定 ToString 方法有任何保证。文件上说 “返回 Expression " .

    (我怀疑输出不太可能在不同的平台/版本之间改变,但是当您的目标是使用强类型、编译时检查等时,我有点不愿意依赖它。)

    我的方法是不用 托斯特林 :

    public static string GetPropertyName<T>(Expression<Func<T, object>> e)
    {
        MemberExpression me;
        switch (e.Body.NodeType)
        {
            case ExpressionType.Convert:
            case ExpressionType.ConvertChecked:
                var ue = e.Body as UnaryExpression;
                me = ((ue != null) ? ue.Operand : null) as MemberExpression;
                break;
            default:
                me = e.Body as MemberExpression;
                break;
        }
    
        if (me == null)
            throw new ArgumentException("Expression must represent field or property access.", "e");
    
        var stack = new Stack<string>();
    
        do
        {
            stack.Push(me.Member.Name);
            me = me.Expression as MemberExpression;
        } while (me != null);
    
        return string.Join(".", stack);    // use "stack.ToArray()" on .NET 3.5
    }
    
        2
  •  2
  •   decyclone    15 年前

    我觉得你的密码没问题。我看没什么问题。为了深入了解这件事,我建议你读 this article this one 也是。

        3
  •  1
  •   Nick Litz    15 年前
        public static string GetPropertyName<T>(Expression<Func<T, object>> e)
        {
            if (e.Body is MemberExpression)
                return ((MemberExpression)e.Body).Member.Name;
            else if (e.Body is UnaryExpression)
                return ((MemberExpression)((UnaryExpression)e.Body).Operand).Member.Name;
    
            throw new ArgumentException("Expression must represent field or property access.", "e");
        }