C# Упрощение выбора свойств в конструкторе с помощью Generi c Тип - PullRequest
3 голосов
/ 13 марта 2020

Я хотел бы упростить некоторый код, если это возможно.

Текущий конструктор (T находится в области видимости, определенной во внешнем типе)

public Column(string propertyName)
{
    PropertyInfo propertyInfo = typeof(T).GetProperty(propertyName);

    _ = propertyInfo ?? throw new ArgumentException(message: $"Property {propertyName} does not exist on {typeof(T).Name}");

    ...
}

Я хочу знать, можно ли сделать property лямбда-выражение или что-то подобное, чтобы выбрать свойство Generi c Тип T.

Это, конечно, облегчает нашу разработку с меньшим количеством ошибки.

Текущее использование

new DataTable<someClass>.Column(nameof(someClass.someProperty))

Я хотел бы сделать что-то вроде:

new DataTable<someClass>.Column(someClass.someProperty) (без объявление нового someClass)

ИЛИ

new DataTable<someClass>.Column(t = > t.someProperty)

Ответы [ 2 ]

4 голосов
/ 13 марта 2020

Вы можете использовать метод ниже, чтобы извлечь имя свойства из выражения

    public static PropertyInfo GetAccessedMemberInfo<T>(this Expression<T> expression)
    {
        MemberExpression? memberExpression = null;

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

        if (memberExpression == null)
        {
            throw new ArgumentException("Not a member access", "expression");
        }

        return memberExpression.Member as PropertyInfo ?? throw new Exception();
    }

Затем используйте его следующим образом

public Column(Expression<Func<T, object>> prop)
{
    PropertyInfo propertyInfo = prop.GetAccessedMemberInfo();
}

new DataTable<someClass>.Column(t = > t.someProperty)
1 голос
/ 13 марта 2020

Предыдущий ответ более полный и поддерживает больше сценариев ios, но также более сложный.

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

namespace ConsoleApp1
{

    public class Column<T, TProperty>
    {
        Func<T, TProperty> functionToBeApplied;

        // Pass a function, it can never throw
        public Column(Func<T, TProperty> functionToBeApplied)
        {
            this.functionToBeApplied = functionToBeApplied;
        }

        // Apply the function to the object
        public string GetPropertyAsString(T obj)
        {
            TProperty property = functionToBeApplied(obj);
            return property.ToString();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {

            var column = new Column<string, int>(x => x.Length);

            Console.WriteLine($"Size of string is {column.GetPropertyAsString("this is my object")}");
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...