4

我有一个常见的问题,我试图以特定的方式解决问题。

基本上使用 Winforms,我试图在表单中设置控件的“DisplayMember”和“ValueMember”。你通常会这样设置:

this.testCombobox.DisplayMember = "PropertyOne";
this.testCombobox.ValueMember = "PropertyTwo";

我想重写如下:

this.testCombobox.DisplayMember = ClassOne.GetPropertyName(c => c.PropertyOne);
this.testCombobox.ValueMember = ClassOne.GetPropertyName(c => c.PropertyTwo);

(注意:2 个方法调用需要是静态的,以便在此处保存创建对象)

我试图这样做的所有类都继承自基类“BaseObject”,所以我向它添加了一个方法,如下所示:

public static string GetPropertyName<T, P>(Expression<Func<T, P>> action) where T : class
{
    MemberExpression expression = action.Body as MemberExpression;
    return expression.Member.Name;
}

但是,为了使用它,我需要编写以下代码:

this.testCombobox.DisplayMember = BaseObject.GetPropertyName((ClassOne c) => c.PropertyOne);

我的问题是,我将如何重写方法BaseObject.GetPropertyName来实现我想要的?我觉得我很接近,但想不出如何改变它。

4

3 回答 3

4

我创建了一个 Helper 类来提取属性名称

  public static class PropertySupport
  {       
    public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
    {
      if (propertyExpression == null)
      {
        throw new ArgumentNullException("propertyExpression");
      }

      var memberExpression = propertyExpression.Body as MemberExpression;
      if (memberExpression == null)
      {
        throw new ArgumentException("Invalide Expression", "propertyExpression");
      }             
      return memberExpression.Member.Name;
    }
  }

您可以按如下方式使用它:

PropertySupport.ExtractPropertyName(() => DateTime.Now)

它将返回“现在”

编辑

这是一个测试控制台应用程序:

  public static class PropertySupport
  {       
    public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
    {
      if (propertyExpression == null)
      {
        throw new ArgumentNullException("propertyExpression");
      }

      var memberExpression = propertyExpression.Body as MemberExpression;
      if (memberExpression == null)
      {
        throw new ArgumentException("", "propertyExpression");
      }      
      return memberExpression.Member.Name;
    }
  }
  public class MyClass
  {
    public MyClass PropertyOne { get; set; }
  }
  class Program
  {    
    static void Main(string[] args)
    {      
      Console.WriteLine(PropertySupport.ExtractPropertyName(() => new MyClass().PropertyOne));
      Console.ReadKey();
    }   
  }
于 2013-07-18T11:20:39.713 回答
4

您当前的 GetPropertyName 方法使通用 T 保持打开状态。因此,编译器无法在编译时解析它,因为您在使用该方法时没有指定它。

但是,如果您将基类设为通用,并在派生类中指定 T,并指定使用派生类(而不是基类)的方法,那么它就可以工作。

像这样:

public class BaseClass<T> {
    public static string GetPropertyName<P>(Expression<Func<T, P>> action) {
        MemberExpression expression = action.Body as MemberExpression;
        return expression.Member.Name;
    }
}

public class ClassOne : BaseClass<ClassOne> {
    public string PropertyOne { get; set; }
}
public static class Test {
    public static void test() {
        var displayMember = ClassOne.GetPropertyName(x => x.PropertyOne);
    }
}
于 2013-07-18T11:29:29.667 回答
0

我会在通用助手中建议以下内容:

    public static class GenericHelper<TEntity> {

        public static string GetPropertyName<TProperty>(Expression<Func<TEntity, TProperty>> propertyExpression) {

            return propertyExpression.GetPropertyName();
        }
    }

以及扩展中的以下常用用法:

public static class ReflectionExtensions {

    public static PropertyInfo GetProperty<TEntity, TProperty>(this Expression<Func<TEntity, TProperty>> source) {

        //TODO: check TEntity, if needed. Now it's ignored

        var member = source.Body as MemberExpression;

        if (member == null) {
            throw new ArgumentException(String.Format(
                "Expression '{0}' refers to a method, not a property.", source));
        }

        var propertyInfo = member.Member as PropertyInfo;

        if (propertyInfo == null) {
            throw new ArgumentException(string.Format(
                "Expression '{0}' refers to a field, not a property.", source));
        }

        return propertyInfo;
    }

    public static string GetPropertyName<TEntity, TProperty>(this Expression<Func<TEntity, TProperty>> source) {

        return source.GetProperty().Name;
    }
}
于 2015-09-06T17:01:04.320 回答