Wednesday, October 21, 2009

Compile-Time Safe DataBinding

No longer will I have to endure the possibilities that the designer's DataBinding broke when I changed the name of something. Nor will have to fret about leaving string literals to point to a property name. Linq Expressions to the rescue! It doesn't work on XAML, but appears to work for everything else.

It works like this:

dtpRequestDate.BindNullableValue(bsTicket, Member.Name<ModelTicket>(ticket => ticket.AddedDate), false);

cmbRequestType.BindNullableSelectedValue(bsTicket,
Member.Name<ModelTicket>(ticket => ticket.RequestTypeId));

Here's the source:

public static class Member

    {

        
private static string GetMemberName(Expression expression)

        {

            
switch (expression.NodeType)

            {

                
case ExpressionType.MemberAccess:

                    
var memberExpression = (MemberExpression)expression;

                    
var supername = GetMemberName(memberExpression.Expression);



                    
if (String.IsNullOrEmpty(supername))

                        
return memberExpression.Member.Name;



                    
return String.Concat(supername, '.', memberExpression.Member.Name);



                
case ExpressionType.Call:

                    
var callExpression = (MethodCallExpression)expression;

                    
return callExpression.Method.Name;



                
case ExpressionType.Convert:

                    
var unaryExpression = (UnaryExpression)expression;

                    
return GetMemberName(unaryExpression.Operand);



                
case ExpressionType.Parameter:

                    
return String.Empty;



                
default:

                    
throw new ArgumentException("The expression is not a member access or method call expression");

            }

        }



        
public static string Name<T>(Expression<Func<T, object>> expression)

        {

            
return GetMemberName(expression.Body);

        }



        
public static string Name<T>(Expression<Action<T>> expression)

        {

            
return GetMemberName(expression.Body);

        }

    }

Thanks to Oliver Hanappi via StackOverflow.com and this post

No comments:

Post a Comment