Это единственный СУХОЙ способ манипулировать коллекциями подтипов? - PullRequest
0 голосов
/ 23 мая 2018

В проекте у меня есть набор классов, которые реализуют абстрактный базовый класс ...

public abstract class BaseClass
{
    Guid Id { get; set; }
    string Name { get; set; }
    string Property { get; set; }
}

public class Foo : BaseClass

public class Bar : BaseClass

/*etc*/

... и для другого класса мне нужно выполнить некоторые манипуляции с ними вколлекция.Единственными вещами, которыми нужно манипулировать, являются члены базового класса.Из-за коллекций довольно сложно написать один метод для каждого типа, и я чувствую, что что-то упустил.Вот что у меня есть:

public ICollection<BaseClass> Transform(ICollection<BaseClass> source, Guid newId, Func<BaseClass> factory)
{
    ICollection<BaseClass> result = new List<BaseClass>();

    foreach (BaseClass x in source)
    {
        BaseClass record = factory();

        record.Id = newId;
        record.Name = x.Name;
        record.Property = x.Property;

        result.Add(record);
    }

    return result;
}

public ICollection<Foo> TransformFoos(ICollection<Foo> source, string property)
{
    Func<BaseClass> factory = () => new Foo();
    ICollection<BaseClass> sourceAsBase = source.Select(x => (BaseClass)x).ToList();
    ICollection<Foo> result = this.Transform(sourceAsBase, property, factory)
                                  .Select(x => (Foo)x)
                                  .ToList();
    return result;
}

public ICollection<Bar> TransformBars(ICollection<Bar> source, string property)

/*etc*/

Это преобразование LOT .Есть ли лучший способ?

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Если вы хотите обновить свойства, определенные для подтипов, вы можете использовать шаблон, соответствующий новой функции C #, вместо написания отдельного метода для каждого подтипа.

    switch(x)
    {
        case Foo f:
            f.Foo1 = "Updated foo";
        break;
        case Bar b:
            b.Bar1 = "Updated bar";
        break;
    }

Ниже вы обновляете метод с тем же.

public static ICollection<BaseClass> Transform(ICollection<BaseClass> source, string property, Func<BaseClass> factory)
{
    ICollection<BaseClass> result = new List<BaseClass>();

    foreach (BaseClass x in source)
    {
        BaseClass record = factory();

        record.Id = x.Id;
        record.Name = x.Name;
        record.Property = property;

        result.Add(record);

        switch(x)
        {
            case Foo f:
                f.Foo1 = "Updated foo";
            break;
            case Bar b:
                b.Bar1 = "Updated bar";
            break;
        }
    }

    return result;
}
0 голосов
/ 24 мая 2018

Практически каждый раз, когда вы видите код, который делает то же самое, но с другим типом, это означает, что вы должны использовать дженерики.Здесь вы можете просто сделать ваш метод преобразования универсальным, ограничить его типами базовых классов, и все готово.

public List<T> Transform<T>(IEnumerable<BaseClass> source, string property)
    where T : BaseClass, new()
{
    return source.Select(sourceItem => new T()
    {
        Id = sourceItem.Id,
        Name = sourceItem.Name,
        Property = property,
    }).ToList();
}
...