views:

1530

answers:

3

I'm working on a method that accepts an expression tree as a parameter, along with a type (or instance) of a class.

The basic idea is that this method will add certain things to a collection that will be used for validation.

public interface ITestInterface
{
    //Specify stuff here.
}

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

The method is called as follows:

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());
}

I'm doing it this way because I'd like for the property names that are passed in to be strong typed.

A couple of things I'm struggling with..

  1. Within DoSomething, I'd like to get a PropertyInfo type (from the body passed in) of T and add it to a collection along with rule[]. Currently, I'm thinking about using expression.Body and removing [propertyname] from "Convert.([propertyname])" and using reflection to get what I need. This seems cumbersome and wrong. Is there a better way?
  2. Is this a specific pattern I'm using?
  3. Lastly, any suggestions or clarifications as to my misunderstanding of what I'm doing are appreciated and / or resources or good info on C# expression trees are appreciated as well.

Thanks!

Ian

Edit:

An example of what expression.Body.ToString() returns within the DoSomething method is a string that contains "Convert(t.MyProperty)" if called from the example above.

I do need it to be strongly typed, so it will not compile if I change a property name.

Thanks for the suggestions!

+1  A: 

Collecting PropertyInfo objects from Expression.Body seems similar to my solution to another question.

Mark Cidade
+2  A: 

I appreciate what you are trying to do with the property here. I have run into this conundrum. It always feels weird to write:

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

If the property ever changes name, or the text is mistyped in the call, then there will be a problem. What I have come to learn is that this is something you probably have to deal with via testing. Specifically, unit testing. I would write unit tests to enforce that the "DoSomething" calls work correctly.

The other thing you might try is to decorate your properties with attributes, and then reflect against your class when it is constructed looking for properties with the attribute, and load rules.

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

In this case the constructor (perhaps in a base class?) would dynamically create an OtherClass object and a OtherClass2 object, and load them into a collection along with the name of the property.

Jason Jackson
The attribute way seems the right way to do it. Something like this which is ad hoc can be provided via the attribute to any consumers that want to use it.
Spence
+2  A: 

I rely heavily on expression trees to push a lot of what I want to do with my current application to compile-time, i.e. static type checking.

I traverse expression trees to translate them into something else which "makes sense".

One thing I've ended up doing a lot is that instead of URLs I rely on a MVC like approach where I declare lambda functions, and translates that... interpret, the compiler generated expression tree into an URL. When this URL is invoked, I do the opposite. This way, I have what I call compile-time checks for broken links and this works great with refactoring and overloads as well. I think it's cool to think about using expression trees in this way.

You might wanna check out the visitor pattern, it's a pain to get started with because it doesn't make much sense in the beginning but it ties everything together and it's a very formal way to solve type checking in compiler construction. You could do the same, but instead of type checking emit what ever you need.

Something which I'm currently pounding my head against is the ability to build a simple framework for translating (or actually I should say interpret) expression tress and emit JavaScript. The idea is that the compiler generated expression trees will translate into valid JavaScript which interfaces with some object model.

What's exciting about this is the way the compiler is always able to tell me when I go wrong and sure the end result is just a bunch of strings but the important part is how these strings got created. They went through some verification and that means something.

Once you get that going there is little you can't do with expression trees.

While working with the System.Reflection.Emit stuff I found myself using expression trees to create a light-weight framework for dynamic compilation, which at compile time could basically say if my dynamically created assemblies would compile as well, and this worked seamlessly with reflection and static type checking. It took this further and further and ended up with something which in the end saved a lot of time and proved to be very agile and robust.

So I love this kind of stuff, and this is what meta programming is all about, writing programs in your programs that do programs. I say keep it coming!

John Leidegren