The client I'm currently working for is using an MVP pattern with WebForms (not WebFormsMVP but an internally developed one) which is using an active view pattern. What this means is that the model contains all the data for both incoming and outgoing requests.

Say a button click happens, the form posts and the model is updated with the data of the input fields, which the presenter then takes over.

This results in a lot of code like this:

txtFirstName.Text = Model.FirstName;
txtLastName.Text = Model.LastName;

Or this:

Model.FirstName = txtFirstName.Text;
Model.LastName = txtLastName.Text;

One of the developers here had finally got sick of typing out model binding code and decided to implement model binding like this:

Bindings.Add(new Binding {
    Data = () => Model.FirstName,
    Ui = () => txtFirstName.Text,
    Direction = BindingDirection.ReadWrite
});

Now this is a pretty neat solution and it solved the problem for the most part. Internally it's using Expression Trees, but it makes two very crutial expectation, Data can only come from Model.PropertyName, meaning you can really work with indexers, etc and Model.PropertyName will return a class not a struct.

I decided that I wanted to use it for something a bit different, I wanted to bind a boolean value to a check box. Unfortuantely this doesn't work as the boolean Expression Tree fails with the expectations listed above.

Thinking that there must be another way to go about this I decided to have a bit of a play around with Expression Trees myself and came up with the following idea.

Note - this isn't actually the code we're using here. We have a .NET 3.5 application and the following code only works in .NET 4.0 due to some changes/ improvements of Expressions Trees.

A quick note on .NET 4.0 Expression Trees

If you haven't really dug around much with Expression Trees in .NET 4.0 you may not be aware that they actually evolved a lot in the new CLR, in fact the .NET 4.0 version is not really an Expression Tree any more, it's actually a Statement Tree and it's scarily close to a full blow Abstract Syntax Tree (AST). Bart De Smet has two really good blogs on the topic, a look at the new Statement Trees and some ways to reduce the pain.

But if you're not into reading those posts the high level view is that in .NET 4.0 you can actually produce Expressions which are more like methods. You can create IfThen statements, variable declarations, loops, etc. And that's pretty cool in my book!

Back to binding

So back at our original experiement I wanted to work out a way I could take the data and the ui, hook them up with an expression to support two-way binding. With .NET 4.0 you can do that really bloody easy since there is an Assign expression which we can play with.

Assign works like this:

Expression.Assign(
    target,
    source
);

This means you can do something like this:

Expression.Assign(
    () => foo.Bar,
    Expression.Constant("bar")
);

What this will do is create an expression which looks like:

foo.Bar = "baz";

Fantastic :D

But let's step back a bit and flesh out a more complete example. First off I need to create some variables to bind:

var foo = new Foo();
var foo2 = new Foo {Bar = "baz"};

Now we'll create some expressions:

Expression<Func<string>> exp1 = () => foo.Bar;
Expression<Func<string>> exp2 = () => foo2.Bar;

When you start breaking apart the expression trees above what you'll find that you have is an expression which has a body of type System.Linq.Expressions.PropertyExpression (which is an internal class!) and if you want to try and break it apart you'll be able to find out the variable you've accessed the property on, as well as the property accessed.

What's cool about a PropertyExpression is that we can do things such as read or write from the property. So now we'll create our assignment expression:

var binder = Expression.Assign(
        exp1.Body,
        exp2.Body
);

Here we're passing in the body of the expression (our PropertyExpression) as both the source and the target, which will result in C# like this:

foo.Bar = foo2.Bar;

Note - you can't really get the C#, it's not possible as all it really can generate is IL and metadata.

So there you go, basic binding done. It's time to compile and ship it!

First create a lambda for us:

var lambda = Expression.Lambda(binder);

Compile the lambda into a Delegate:

var func = lambda.Compile();

Execute the delegate:

func.DynamicInvoke();
Console.WriteLine(foo.Bar); //baz

You can then update foo2 and recall the delegate:

foo2.Bar = "Hello World!";
func.DynamicInvoke();
Console.WriteLine(foo.Bar); //Hello World!

Conclusion

This above code is actually not tied to WebForms, or any particular UI of .NET, you could use it in anything that supported the .NET 4.0 expression trees.

Keep in mind that this is a thought expermiment and I haven't exactly done a lot of testing of the code. All I know is that it worked in my basic tests :P. Since we're using .NET 3.5 at this client I'm not able to actually put it into the framework, so I'm just leaving it here as a thought experiement.

If you're interested in the full code it is here.

blog comments powered by Disqus