帮助定义泛型方法以及表达式树参数

时间:2011-04-17 14:05:25

标签: c# generics expression-trees

假设我有:

class Person
{
[ColumnAttribute("ID"]
    public int Id;
[ColumnAttribute("Name"]
public string Name;
[ColumnAttribute("DateOfBirth"]
    public date BirthDate;
}

我想创建一个将被调用的方法

GetPropertyColumn<Person>(e=>e.Name)

此方法将返回由ColumnAttribute属性定义的字符串 问题是我无法定义此方法。 我试过了

public string GetPropertyColumn<T,U>(Expression<Func<T, U>> Lamda)

但问题是,我只能指定T而不是U,所以它不起作用 任何帮助?
感谢

编辑:

感谢您的答案,但我得到了很多答案,您需要即时通知人员,但我不想这样。
因为我只想知道给定在类中定义的属性的列。

3 个答案:

答案 0 :(得分:2)

[编辑3]

    public static string GetPropertyColumn<T>(Expression<Func<T,object>> f)
    {
        Type t = typeof(T);

        MemberExpression memberExpression = null;

        if (f.Body.NodeType == ExpressionType.Convert)
        {
            memberExpression = ((UnaryExpression)f.Body).Operand as MemberExpression;
        }
        else if (f.Body.NodeType == ExpressionType.MemberAccess)
        {
            memberExpression = f.Body as MemberExpression;
        }

        string name = memberExpression.Member.Name;

        System.Reflection.FieldInfo fi = t.GetField(name);
        object[] attrs = fi.GetCustomAttributes(true);

        foreach (var attr in attrs)
        {
            ColumnAttribute columnAttr = attr as ColumnAttribute;
            if (columnAttr != null)
            {
                return columnAttr.Name;
            }
        }

        return string.Empty;
    }

使用:

Console.WriteLine(GetPropertyColumn<Person>(e => e.Name));

答案 1 :(得分:2)

如果你有一个带有2种泛型类型(T和U)的泛型方法,那么两者都被指定,或者两者都被推断出来。如果无法做到这一点,请考虑使用Func<T,object>(删除U)的表达式,并在运行时检查表达式树时从表达式树中删除强制转换/转换节点。您也可以做一些事情来推断这两种类型,但这可能需要更多的重构。

答案 2 :(得分:1)

将其作为扩展方法:

static class ExtensionMethods
{
    public static string GetPropertyColumn<T,U>(this T obj, Expression<Func<T, U>> selector)
    {
        ... // whatever
    }
}

使用如下:

Person person = ...
string propertyColumn = person.GetPropertyColumn(p => p.Name);

您不需要指定T,因为它是从第一个参数推断出来的,并且您不需要指定U,因为它是从lambda的返回类型推断的

请注意,您不需要将其定义为扩展方法,它也可以是常规方法。然后你会像那样使用它:

Person person = ...
string propertyColumn = GetPropertyColumn(person, p => p.Name);