Общий метод для установки значения свойства с помощью выражений/лямбда

113
17

Я пытаюсь найти общий способ присвоить значения свойствам, продиктованному выражением лямбда, посмотреть примерный код ниже, как будет выглядеть сигнатура для метода 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();
}
}

спросил(а) 2021-01-19T14:25:24+03:00 9 месяцев, 1 неделя назад
1
Решение
103

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


 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();
}
}


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


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


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

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


this List<long> entities,

Хороший вопрос.


ИЗМЕНИТЬ Исправление предложения кода.

ответил(а) 2021-01-19T14:25:24+03:00 9 месяцев, 1 неделя назад
79

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


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

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


public static List<T> ConvertToEntities<TProp, T>(
this List<TProp> dataIds, Action<T, TProp> lambdaProperty)
where T : new()
{
return dataIds.Select(
p =>
{
var result = new T();
lambdaProperty(result, p);
return result;
}).ToList();
}

ответил(а) 2021-01-19T14:25:24+03:00 9 месяцев, 1 неделя назад
66

Я считаю, что @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 } );

ответил(а) 2021-01-19T14:25:24+03:00 9 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема