这可能适用于其他地方,但在WinForms中,当我使用绑定时,我发现许多方法都希望将属性的名称绑定到.就像是:
- class Person
- {
- public String Name { get { ... } set { ... } }
- public int Age { get { ... } set { ... } }
- }
- class PersonView
- {
- void Bind(Person p)
- {
- nameControl.Bind(p,"Name");
- ageControl.Bind(p,"Age");
- }
- }
我一直遇到的一个大问题是“Name”和“Age”被指定为字符串.这意味着如果有人重命名Person的一个属性,编译器就无济于事.代码编译正常,但绑定将被破坏.
我错过了解决这个问题的标准方法吗?感觉我需要一些关键字,也许叫做stringof来匹配现有的typeof.你可以使用它:
- ageControl.Bind(p,stringof(p.Age).Name);
stringof可以返回一些具有获取完整路径,路径的一部分或字符串的属性的类,以便您可以自己解析它.
这样的事情已经可以吗?
解决方法
您可以使用表达式来获取编译器检查的绑定.
例如,在当前的一个项目中,我们设置了这样的绑定:
例如,在当前的一个项目中,我们设置了这样的绑定:
- DataBinder
- .BindToObject(this)
- .ObjectProperty(c => c.IsReadOnly)
- .Control(nameTextBox,n => n.ReadOnly)
- .Control(addressControl,n => n.ReadOnly)
- public static class DataBinder
- {
- public static DataBinderBindingSourceContext<TDataSource> BindToObject<TDataSource>(TDataSource dataSource)
- {
- return new DataBinderBindingSourceContext<TDataSource>(dataSource);
- }
- }
- public class DataBinderBindingSourceContext<TDataSource>
- {
- public readonly object DataSource;
- public DataBinderBindingSourceContext(object dataSource)
- {
- DataSource = dataSource;
- }
- public DataBinderControlContext<TDataSource,TProperty> ObjectProperty<TProperty>(Expression<Func<TDataSource,TProperty>> property)
- {
- return new DataBinderControlContext<TDataSource,TProperty>(this,property);
- }
- }
- public class DataBinderControlContext<TDataSource,TProperty>
- {
- readonly DataBinderBindingSourceContext<TDataSource> BindingSourceContext;
- readonly string ObjectProperty;
- public DataBinderControlContext
- (
- DataBinderBindingSourceContext<TDataSource> bindingSourceContext,Expression<Func<TDataSource,TProperty>> objectProperty
- )
- {
- BindingSourceContext = RequireArg.NotNull(bindingSourceContext);
- ObjectProperty = ExpressionHelper.GetPropertyName(objectProperty);
- }
- public DataBinderControlContext<TDataSource,TProperty> Control<TControl>(TControl control,Expression<Func<TControl,TProperty>> property)
- where TControl : Control
- {
- var controlPropertyName = ExpressionHelper.GetPropertyName(property);
- control.DataBindings.Add(controlPropertyName,BindingSourceContext.DataSource,ObjectProperty,true);
- return this;
- }
- }
- public static class ExpressionHelper
- {
- public static string GetPropertyName<TResult>(Expression<Func<TResult>> property)
- {
- return GetMemberNames(((LambdaExpression)property).Body).Skip(1).Join(".");
- }
- public static string GetPropertyName<T,TResult>(Expression<Func<T,TResult>> property)
- {
- return GetMemberNames(((LambdaExpression)property).Body).Join(".");
- }
- static IEnumerable<string> GetMemberNames(Expression expression)
- {
- if (expression is ConstantExpression || expression is ParameterExpression)
- yield break;
- var memberExpression = (MemberExpression)expression;
- foreach (var memberName in GetMemberNames(memberExpression.Expression))
- yield return memberName;
- yield return memberExpression.Member.Name;
- }
- }
- public static class StringExtentions
- {
- public static string Join(this IEnumerable<string> values,string separator)
- {
- if (values == null)
- return null;
- return string.Join(separator,values.ToArray());
- }
- }