Enlace de datos de Windows Forms tipificado fuerte

Estoy buscando en el enlace de datos de Windows Forms con métodos de extensión. Tengo la siguiente ayuda de Xavier como sigue:

using System; using System.Linq.Expressions; using System.Windows.Forms; namespace WindowsFormsApplication1 { public static Binding Add (this ControlBindingsCollection dataBindings, object dataSource, Expression<Func> controlExpression, Expression<Func> objectExpression) { return Add(dataBindings, dataSource, controlExpression, objectExpression, false); } public static Binding Add (this ControlBindingsCollection dataBindings, object dataSource, Expression<Func> controlExpression, Expression<Func> objectExpression, bool formattingEnabled) { string controlPropertyName = ProcessExpression(controlExpression.Body); string bindingTargetName = ProcessExpression(objectExpression.Body); return dataBindings .Add(controlPropertyName, dataSource, bindingTargetName, formattingEnabled); } public static Binding Add (this ControlBindingsCollection dataBindings, object dataSource, Expression<Func> controlExpression, Expression<Func> objectExpression) { return Add(dataBindings, dataSource, controlExpression, objectExpression, false); } public static Binding Add (this ControlBindingsCollection dataBindings, object dataSource, Expression<Func> controlExpression, Expression<Func> objectExpression, bool formattingEnabled ) { string controlPropertyName = ProcessExpression(controlExpression.Body); string bindingTargetName = ProcessExpression(objectExpression.Body); return dataBindings.Add(controlPropertyName, dataSource, bindingTargetName, formattingEnabled); } private static string ProcessExpression(Expression expression) { string propertyName; if (expression is MemberExpression) { propertyName = ((MemberExpression) (expression)).Member.Name; } else if (expression is UnaryExpression) { propertyName = ((MemberExpression) ((UnaryExpression) (expression)).Operand).Member.Name; } else { throw new InvalidOperationException( "Unknown expression type error in DataBindingsExtensionMethods.Add"); } return propertyName; } } 

Ahora puedo configurar un enlace de datos como este:

 txtBoundInt.DataBindings.Add (bindingSource, tb => tb.Text, contact => contact.Id); 

O esto:

 cboBoundSelectedItem.DataBindings.Add  (bindingSource, cbo => cbo.SelectedItem, con => con.ContactType) 

Sin embargo, parece que hay una gran cantidad de expresiones en marcha. ¿Hay alguna manera mejor?


Edit: Encontré una mejor manera, pero me metí en problemas por cambiar esta pregunta a esa respuesta, se reproduce a continuación por @Carl_G.

¿Qué hay de establecer el tipo de retorno a objeto?

 public static Binding Add (this ControlBindingsCollection dataBindings, object dataSource, Expression> controlLambda, Expression> objectLambda) { string controlPropertyName = ((MemberExpression)(controlLambda.Body)).Member.Name; string bindingTargetName = ((MemberExpression)(objectLambda.Body)).Member.Name; return dataBindings.Add (controlPropertyName, dataSource, bindingTargetName); } 

Como la pregunta se ha editado para incluir solo una respuesta, incluyo esa respuesta aquí. El autor probablemente debería haber dejado la pregunta original solo y publicado una respuesta a su propia pregunta. Pero parece ser una muy buena solución.


Edición: prefiero esta solución que encontré finalmente en el caché de Google (se eliminó del sitio del autor ) ya que solo necesita una especificación de tipo. No sé por qué el autor original lo borró.

 // Desired call syntax: nameTextBox.Bind(t => t.Text, aBindingSource, (Customer c) => c.FirstName); // Binds the Text property on nameTextBox to the FirstName property // of the current Customer in aBindingSource, no string literals required. // Implementation. public static class ControlExtensions { public static Binding Bind (this TControl control, Expression> controlProperty, object dataSource, Expression> dataSourceProperty) where TControl: Control { return control.DataBindings.Add (PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty)); } } public static class PropertyName { public static string For(Expression> property) { var member = property.Body as MemberExpression; if (null == member) { var unary = property.Body as UnaryExpression; if (null != unary) member = unary.Operand as MemberExpression; } return null != member ? member.Member.Name : string.Empty; } } 

He estado usando el código publicado por Stuart desde hace unos meses. Agregué algunas sobrecargas más para que coincidan con el rest de los escenarios de enlace de datos que querrás usar (solo lo estoy publicando aquí para que otros tengan un tiempo aún más fácil para que funcione esta cosa muy útil)

  public static class ControlExtensions { /// Databinding with strongly typed object names /// The Control you are binding to /// The property on the control you are binding to /// The object you are binding to /// The property on the object you are binding to public static Binding Bind(this TControl control, Expression> controlProperty, object dataSource, Expression> dataSourceProperty) where TControl :Control { return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty)); } public static Binding Bind(this TControl control, Expression> controlProperty, object dataSource, Expression> dataSourceProperty, bool formattingEnabled = false) where TControl :Control { return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty), formattingEnabled); } public static Binding Bind(this TControl control, Expression> controlProperty, object dataSource, Expression> dataSourceProperty, bool formattingEnabled, DataSourceUpdateMode updateMode) where TControl :Control { return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty), formattingEnabled, updateMode); } public static Binding Bind(this TControl control, Expression> controlProperty, object dataSource, Expression> dataSourceProperty, bool formattingEnabled, DataSourceUpdateMode updateMode, object nullValue) where TControl :Control { return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty), formattingEnabled, updateMode, nullValue); } public static Binding Bind(this TControl control, Expression> controlProperty, object dataSource, Expression> dataSourceProperty, bool formattingEnabled, DataSourceUpdateMode updateMode, object nullValue, string formatString) where TControl :Control { return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty), formattingEnabled, updateMode, nullValue, formatString); } public static Binding Bind(this TControl control, Expression> controlProperty, object dataSource, Expression> dataSourceProperty, bool formattingEnabled, DataSourceUpdateMode updateMode, object nullValue, string formatString, IFormatProvider formatInfo) where TControl :Control { return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty), formattingEnabled, updateMode, nullValue, formatString, formatInfo); } public static class PropertyName { public static string For(Expression> property) { var member = property.Body as MemberExpression; if(null == member) { var unary = property.Body as UnaryExpression; if(null != unary) member = unary.Operand as MemberExpression; } return null != member ? member.Member.Name : string.Empty; } } }