【问题标题】:Advice on C# Expression Trees关于 C# 表达式树的建议
【发布时间】:2008-10-01 01:00:42
【问题描述】:

我正在研究一种接受表达式树作为参数的方法,以及类的类型(或实例)。

基本思想是,此方法会将某些内容添加到将用于验证的集合中。

public interface ITestInterface
{
    //Specify stuff here.
}

private static void DoSomething<T>(Expression<Func<T, object>> expression, params IMyInterface[] rule)
{
    // Stuff is done here.
}

方法调用如下:

class TestClass
{
    public int MyProperty { get; set; }
}

class OtherTestClass  : ITestInterface
{
    // Blah Blah Blah.
}

static void Main(string[] args)
{
    DoSomething<TestClass>(t => t.MyProperty, 
        new OtherTestClass());
}

我这样做是因为我希望传入的属性名称是强类型的。

我正在努力解决的几件事..

  1. 在DoSomething 中,我想获得T 的PropertyInfo 类型(从传入的主体)并将其与规则[] 一起添加到集合中。目前,我正在考虑使用 expression.Body 并从“Convert.([propertyname])”中删除 [propertyname] 并使用反射来获得我需要的东西。这看起来既麻烦又错误。有没有更好的方法?
  2. 这是我正在使用的特定模式吗?
  3. 最后,感谢任何关于我对自己所做工作的误解的建议或澄清和/或有关 C# 表达式树的资源或良好信息。

谢谢!

伊恩

编辑:

expression.Body.ToString() 在 DoSomething 方法中返回的示例是一个包含“Convert(t.MyProperty)”的字符串(如果从上面的示例调用)。

我确实需要它是强类型的,所以如果我更改属性名称,它将无法编译。

感谢您的建议!

【问题讨论】:

    标签: c# reflection expression-trees


    【解决方案1】:

    我严重依赖表达式树将我想要对当前应用程序执行的许多操作推送到编译时,即静态类型检查。

    我遍历表达式树,将它们翻译成“有意义”的其他东西。

    我最终做了很多事情是,我依赖于类似 MVC 的方法来声明 lambda 函数,然后将其翻译...解释,编译器将生成的表达式树转换为 URL,而不是 URL。当调用这个 URL 时,我做相反的事情。通过这种方式,我可以对断开的链接进行编译时检查,这对于重构和重载也很有效。我认为以这种方式使用表达式树很酷。

    您可能想查看访问者模式,开始使用它很痛苦,因为它一开始并没有多大意义,但它将所有内容联系在一起,并且它是解决编译器构造中类型检查的一种非常正式的方法。你也可以这样做,但不是类型检查,而是发出你需要的东西。

    我目前正在努力解决的问题是能够构建一个简单的框架来翻译(或者实际上我应该说是解释)表达式树并发出 JavaScript。这个想法是编译器生成的表达式树将转换为与某些对象模型接口的有效 JavaScript。

    令人兴奋的是,当我出错时编译器总是能够告诉我,并确保最终结果只是一堆字符串,但重要的是这些字符串是如何创建的。他们通过了一些验证,这意味着什么。

    一旦你做到了,你就可以用表达式树做点什么了。

    在使用 System.Reflection.Emit 的过程中,我发现自己使用表达式树来创建一个用于动态编译的轻量级框架,在编译时它基本上可以说明我的动态创建的程序集是否也可以编译,这很有效与反射和静态类型检查无缝连接。它越走越远,最终得到了一些东西,最终节省了很多时间,并且被证明非常敏捷和健壮。

    所以我喜欢这种东西,这就是元编程的全部内容,在你的程序中编写程序来执行程序。我说继续!

    【讨论】:

      【解决方案2】:

      从 Expression.Body 收集 PropertyInfo 对象似乎类似于 my solution 另一个问题。

      【讨论】:

        【解决方案3】:

        我很欣赏您尝试对这里的财产做些什么。我遇到了这个难题。写起来总感觉怪怪的:

        DoSomething("MyProperty", new OtherClass());
        

        如果属性曾经更改名称,或者在调用中输入错误的文本,那么就会出现问题。我了解到的是,这可能是您必须通过测试来处理的问题。具体来说,单元测试。我会编写单元测试来强制“DoSomething”调用正常工作。

        您可能会尝试的另一件事是用属性装饰您的属性,然后在构造类时反映您的类,查找具有该属性的属性并加载规则。

        [DoSomething(typeof(OtherClass), typeof(OtherClass2))]
        public int MyProperty
        {
          get;
          set;
        }
        

        在这种情况下,构造函数(可能在基类中?)将动态创建一个 OtherClass 对象和一个 OtherClass2 对象,并将它们与属性名称一起加载到一个集合中。

        【讨论】:

        • 属性方式似乎是正确的做法。可以通过属性向任何想要使用它的消费者提供类似这样的临时性的东西。
        猜你喜欢
        • 2015-07-19
        • 1970-01-01
        • 1970-01-01
        • 2013-07-02
        • 2018-03-11
        • 2015-04-13
        • 1970-01-01
        • 2015-05-23
        • 1970-01-01
        相关资源
        最近更新 更多