使用Intellisense和编译时检查提取反射的属性名称

GWL*_*osa 14 c# mapping reflection intellisense compile-time

好.所以我有一些代码将winForm上的某些控件映射到对象中的某些属性,以便在数据发生某些事情时对控件执行某些操作.一切都很好,工作得很好.不是问题.问题是,要将项添加到映射中,我调用的函数看起来像:

this.AddMapping(this.myControl,myObject,"myObjectPropertyName");
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是,在编译时很难说出上述行与下面的行之间的区别:

this.AddMapping(this.myControl,myObject,"myObjectPropretyName");
Run Code Online (Sandbox Code Playgroud)

由于最后一个参数是一个字符串,因此没有编译时检查或类似的任何东西会强制字符串本身实际上对应于给定对象上的有效属性名称.此外,Refactor和"查找所有引用"之类的内容错过了这种引用,当属性名称发生变化时会导致欢闹.所以我想知道的是,是否有某种方法可以更改函数,以便我传入的内容仍然是以某种方式表示属性名称的字符串,但是使用编译时检查实际值是否进入.有人说我可以用Expression Trees做到这一点,但我已经阅读了它们,似乎没有看到连接.我喜欢做类似的事情:

this.AddMapping(this.myControl,myObject,myObject.myObjectPropertyName);
Run Code Online (Sandbox Code Playgroud)

甚至

this.AddMapping(this.myControl,myObject.myObjectPropertyName);
Run Code Online (Sandbox Code Playgroud)

会很甜蜜!

有任何想法吗?

Mar*_*ell 15

在3.5中,Expression是一种将成员名称指定为代码的方法; 你可以有:

public void AddMapping<TObj,TValue>(Control myControl, TObj myObject,
       Expression<Func<TObj, TValue>> mapping) {...}
Run Code Online (Sandbox Code Playgroud)

然后解析表达式树以获取值.效率有点低,但也不算太差.

这是示例代码:

    public void AddMapping<TSource, TValue>(
        Control control,
        TSource source,
        Expression<Func<TSource, TValue>> mapping)
    {
        if (mapping.Body.NodeType != ExpressionType.MemberAccess)
        {
            throw new InvalidOperationException();
        }
        MemberExpression me = (MemberExpression)mapping.Body;
        if (me.Expression != mapping.Parameters[0])
        {
            throw new InvalidOperationException();
        }
        string name = me.Member.Name;
        // TODO: do something with "control", "source" and "name",
        // maybe also using "me.Member"
    }
Run Code Online (Sandbox Code Playgroud)

叫来:

    AddMapping(myControl, foo, f => f.Bar);
Run Code Online (Sandbox Code Playgroud)