Объединить (Список list, строка, указанная propertyoft)?

#c# #linq #generics #reflection #collections

#c# #linq #общие #отражение #Коллекции

Вопрос:

От параметра к свойству?

 public class ConcatenateListTMember
{
    public static void Test()
    {
        var someList = new List<AnyClass>();
        someList.Add(new AnyClass("value1"));
        someList.Add(new AnyClass("value2"));
        Console.WriteLine(Concatenate(someList, "SomeProperty"));
        Console.ReadLine();
    }

    static string Concatenate<T>(List<T> list, string specifiedPropertyOfT)
    {
        string output = String.Empty;
        // TODO: Somehow concatenate all the specified property elements in the list?
        return output;
    }
}

internal class AnyClass
{
    public AnyClass(string someProperty)
    {
        SomeProperty = someProperty;
    }

    public string SomeProperty { get; set; }
}
 

Как можно реализовать универсальный метод в этом примере кода?

  • Пожалуйста, обратите внимание, что specifiedPropertyOfT это не обязательно должна быть строка, если та же цель может быть достигнута с использованием другого типа.
  • В идеале отражение не требовалось бы 🙂

Ответ №1:

Я думаю, вы ищете новые перегрузки string.Join в .NET 4, которые позволили бы:

 IEnumerable<AnyClass> sequence = ...;
string joined = string.Join(",", sequence.Select(x => x.SomeProperty));
 

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

Обратите внимание, что селектор в Select не должен возвращать строки — String.Join будет вызывать ToString любые нестроковые значения.

Ответ №2:

Еще лучше — метод расширения:

 static string Concatenate<T>(this IEnumerable<T> list, Func<T,string> func)
{
    return String.Join("",list.Select(func));
}
 

Использование:

 someList.Concatenate(i => i.SomeProperty);
 

Живой пример: http://rextester.com/runcode?code=LRA78268

Ответ №3:

Попробуйте что-то вроде этого. Я создал метод расширения для IEnumerable:

 public static class Extension
{
    public static string ConcatinateString<T>(this IEnumerable<T> collection, Func<T, string> GetValue)
    {
        StringBuilder sb = new StringBuilder();
        foreach (var item in collection)
        {
            sb.Append(GetValue(item));
        }
        return sb.ToString();
    }
}
 

Тогда назовите это так, вы бы использовали что-то вроде этого:

 var values = new List<TestClass>
        {
            new TestClass(){Name="John",Comment="Hello"},
            new TestClass(){Name="Smith", Comment="Word"}
        };
string s = values.ConcatinateString((x => x.Name));
string v = values.ConcatinateString((x => x.Comment));
 

В этом примере s = "JohnSmith" и v = "HelloWord" . Функция Func() дает вам гибкость. По сути, вы указываете функции, куда идти, чтобы получить строку для конкатенации. Я также использовал StringBuilder на случай, если вы работаете с длинными коллекциями.