3

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

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

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

谢谢!

伊恩

编辑:

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

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

感谢您的建议!

4

3 回答 3

3

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

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

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

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

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

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

一旦你做到了,你就不能用表达式树做任何事情。

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

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

于 2009-01-07T21:17:02.797 回答
2

从 Expression.Body 收集 PropertyInfo 对象似乎类似于对另一个问题的解决方案。

于 2008-10-01T01:20:17.030 回答
2

我很欣赏你在这里试图处理的财产。我遇到了这个难题。写起来总感觉怪怪的:

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

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

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

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

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

于 2008-10-01T01:28:06.450 回答