Общий метод для установки значения свойства с помощью выражений / лямбда - PullRequest
5 голосов
/ 14 февраля 2012

Я пытаюсь найти общий способ присвоения значений свойству, продиктованному лямбда-выражением, посмотрите на приведенный ниже пример кода, как будет выглядеть подпись для метода ConverToEntities и как она будет вызываться?

static void Main()
{
    List<long> ids = new List<long> {1, 2, 3};

    //Non generic way
    List<Data> dataItems = ids.ConvertToDataItems();

    //Generic attempt!!
    List<Data> differntDataItems =
        ids.ConvertToEntities<Data>( p => p.DataId );
}

public class Data
{
    public long DataId;
    public string Name;
}

public static class ExtensionMethods
{
    public static List<Data> ConvertToDataItems(this List<long> dataIds)
    {
        return dataIds.Select(p => new Data { DataId = p }).ToList();
    }

    public static List<T> ConvertToEntities<TProp>(
        this List<long> entities, Func<TProp> lambdaProperty )
    {
        return entities.Select(p => new T {lambdaProperty} ).ToList();
    }
}

Ответы [ 3 ]

4 голосов
/ 14 февраля 2012

Хорошо.Самое близкое, что я мог получить, было это:

 class Program
    {
        static void Main(string[] args)
        {
            List<long> ids = new List<long> { 1, 2, 3 };

            //Non generic way
            List<Data> dataItems = ids.ConvertToDataItems();

            //Generic attempt!!

            Func<long, Data> selector = (p => new Data { DataId = p });
            List<Data> differntDataItems = ids.ConvertToEntities<Data>(selector);
        }
    }

    public class Data
    {
        public long DataId;
        public string Name;
    }

    public static class ExtensionMethods
    {
        public static List<Data> ConvertToDataItems(this List<long> dataIds)
        {
            return dataIds.Select(p => new Data { DataId = p }).ToList();
        }

        public static List<TProp> ConvertToEntities<TProp>(this List<long> entities, Func<long, TProp> selector)
        {
            return entities.Select(selector).ToList();
        }
    }

Это работает.

У меня такое чувство, что вы немного запутались с тем, что вы на самом деле хотите в качестве возвращаемого типа.Было бы круто иметь возможность указать, что мы хотим в вызове метода или что-то в этом роде.Например:

    public static List<TProp> ConvertToEntities<T, TProp>(List<T> entities, Func<T, TProp> selector)
    {
        return entities.Select(selector).ToList();
    }

Это обеспечивает нам большую гибкость в отношении типа возвращаемого значения.Но так как мы делаем это с использованием расширений, я предполагаю, что это нецелесообразно, потому что нам нужно знать, какой тип мы расширяем:

РЕДАКТИРОВАТЬ Исправлено предложение кода.

2 голосов
/ 14 февраля 2012

Вы можете сделать что-то подобное, но это не так просто или приятно.Лямбда p => p.DataId дает вам доступ к собственности.Вы можете использовать Expression s, чтобы получить установщик, но, вероятно, лучше использовать установщик непосредственно в лямбда-выражении:

List<Data> differntDataItems =
    ids.ConvertToEntities<long, Data>((p, i) => p.DataId = i);

Реализация будет выглядеть так:

1 голос
/ 14 февраля 2012

Я считаю, что @Zortkun прав насчет типа возвращаемого значения Попробуйте следующее:

public static List<TProp> ConvertToEntities<TProp>(
    this List<long> entities, Func<long, TProp> lambdaProperty )
{
    return entities.Select(lambdaProperty).ToList();
}

и вы бы назвали это следующим образом:

ids.ConvertToEntities<Data>( p => new Data { DataId = p } );
...