C# 使用表达式、静态方法和基对象获取类的属性名

C# 使用表达式、静态方法和基对象获取类的属性名,c#,.net,linq,c#-4.0,C#,.net,Linq,C# 4.0,我有一个共同的问题,那就是我正试图以一种特定的方式绕开 基本上,对于Winforms,我试图在表单中设置控件的“DisplayMember”和“ValueMember”。您通常会这样设置: this.testCombobox.DisplayMember = "PropertyOne"; this.testCombobox.ValueMember = "PropertyTwo"; 我想重写如下: this.testCombobox.DisplayMember = ClassOne.GetProp

我有一个共同的问题,那就是我正试图以一种特定的方式绕开

基本上,对于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);
public static string GetPropertyName<T, P>(Expression<Func<T, P>> action) where T : class
{
    MemberExpression expression = action.Body as MemberExpression;
    return expression.Member.Name;
}
(注意:这两个方法调用需要是静态的,才能保存在此处创建对象)

我尝试执行此操作的所有类都继承自基类“BaseObject”,因此我向其添加了一个方法,如下所示:

this.testCombobox.DisplayMember = ClassOne.GetPropertyName(c => c.PropertyOne);
this.testCombobox.ValueMember = ClassOne.GetPropertyName(c => c.PropertyTwo);
public static string GetPropertyName<T, P>(Expression<Func<T, P>> action) where T : class
{
    MemberExpression expression = action.Body as MemberExpression;
    return expression.Member.Name;
}

我的问题是,如何重写方法
BaseObject.GetPropertyName
,以实现我想要的?我觉得自己非常接近,但无法思考如何更改它。

我创建了一个帮助器类来提取属性名称

  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;
    }
  }
它将返回“现在”

编辑

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

  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();
    }   
  }
公共静态类属性支持
{       
公共静态字符串ExtractPropertyName(表达式propertyExpression)
{
if(propertyExpression==null)
{
抛出新ArgumentNullException(“propertyExpression”);
}
var memberExpression=propertyExpression.Body作为memberExpression;
if(memberExpression==null)
{
抛出新的ArgumentException(“,“propertyExpression”);
}      
返回memberExpression.Member.Name;
}
}
公共类MyClass
{
公共MyClass PropertyOne{get;set;}
}
班级计划
{    
静态void Main(字符串[]参数)
{      
Console.WriteLine(PropertySupport.ExtractPropertyName(()=>new MyClass().PropertyOne));
Console.ReadKey();
}   
}

当前的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);
    }
}
公共类基类{
公共静态字符串GetPropertyName

(表达式操作){ MemberExpression=action.Body作为MemberExpression; 返回表达式.Member.Name; } } 公共类ClassOne:基类{ 公共字符串属性one{get;set;} } 公共静态类测试{ 公共静态无效测试(){ var displayMember=ClassOne.GetPropertyName(x=>x.PropertyOne); } }


我建议在generic helper中使用以下内容:

    public static class GenericHelper<TEntity> {

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

            return propertyExpression.GetPropertyName();
        }
    }
公共静态类GenericHelper{
公共静态字符串GetPropertyName(表达式propertyExpression){
返回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;
    }
}
公共静态类ReflectionExtensions{
公共静态属性Info GetProperty(此表达式源){
//TODO:如果需要,检查tenty。现在它被忽略了
var member=source.Body作为MemberExpression;
if(成员==null){
抛出新ArgumentException(String.Format(
表达式“{0}”引用的是方法,而不是属性。“,source”);
}
var propertyInfo=member.member作为propertyInfo;
如果(propertyInfo==null){
抛出新ArgumentException(string.Format(
表达式“{0}”引用的是字段,而不是属性。“,source”);
}
返回属性信息;
}
公共静态字符串GetPropertyName(此表达式源){
返回source.GetProperty().Name;
}
}

您将如何调用此方法来获取实际类的属性名?我已经尝试了您在这里拥有的功能,但无法使其正常工作。一个简单的调用,如PropertySupport.ExtractPropertyName(()=>YouClassInstance.Property)。我在我所有的项目中都使用它,它对我来说非常好。啊,好吧,这是一个我从未尝试过的新对象的更新。完美,就是它。谢谢你,马丁!