помогите определить общий метод вместе с параметром дерева выражений - PullRequest
1 голос
/ 17 апреля 2011

Предположим, у меня есть:

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, поэтому он не работает.
любая помощь?
спасибо

Edit:

спасибо за ответы, но у меня есть много ответов, в которых вам нужно мгновенно включить Person, но я не хочу.
потому что я хочу знать только столбец с заданным свойством, определенным внутри класса.

Ответы [ 3 ]

2 голосов
/ 17 апреля 2011

Если у вас есть универсальный метод с 2 универсальными типами (T и U), тогда оба будут указываться наиболее или оба будут выведены. Если это невозможно, рассмотрите выражение, принимающее Func<T,object> (удалить U), и удалите узел преобразования / преобразования из дерева выражений при проверке его во время выполнения. Вы также можете сделать что-то, чтобы сделать оба типа выводными, но для этого может потребоваться больше рефакторинга.

2 голосов
/ 17 апреля 2011

[РЕДАКТИРОВАТЬ 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 голос
/ 17 апреля 2011

Сделайте это методом расширения:

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, потому что он выводится из типа возврата лямбды

Обратите внимание, что вам не нужно , чтобы определить его как метод расширения, он также может быть обычным методом. Вы бы тогда использовали это так:

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