我有一个共同的问题,我正试图以特定的方式绕过。
基本上使用Winforms,我试图设置" DisplayMember"和#34; 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
以实现我想要的目标?我觉得我很亲密,但想不出怎么改变它。
答案 0 :(得分:4)
我创建了一个Helper类来提取Proprty 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("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();
}
}
答案 1 :(得分: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);
}
}
答案 2 :(得分: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;
}
}