Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic extension method to convert from one collection to another

Tags:

c#

generics

I'm working in a code base which has a lot of first class collections.

In order to ease using these collections with LINQ, there is an extension method per collection that looks like:

public static class CustomCollectionExtensions
{
    public static CustomCollection ToCustomCollection(this IEnumerable<CustomItem> enumerable)
    {
        return new CustomCollection(enumerable);
    }
}

With the accompanying constructors:

public class CustomCollection : List<CustomItem>
{
    public CustomCollection(IEnumerable<CustomItem> enumerable) : base(enumerable) { }
}

This winds up being a bunch of boilerplate so I attempted to write a generic IEnumerable<U>.To<T>() so that we wouldn't have to keep generating these specific ToXCollection() methods.

I got as far as:

public static class GenericCollectionExtensions
{
    public static T To<T, U>(this IEnumerable<U> enumerable) where T : ICollection<U>, new()
    {
        T collection = new T();
        foreach (U u in enumerable)
        {
            collection.Add(u);
        }
        return collection;
    }
}

Which has to be called like customCollectionInstance.OrderBy(i => i.Property).To<CustomCollection, CustomItem>()

Is there a way to avoid having to specify the CustomItem type so we can instead use customCollectionInstance.OrderBy(i => i.Property).To<CustomCollection>() or is this not something that can be done generically?

like image 977
Justin Edwards Avatar asked Nov 14 '13 23:11

Justin Edwards


1 Answers

Something close to what you want:

public static class GenericCollectionExtensions
{
    public sealed class CollectionConverter<TItem>
    {
        private readonly IEnumerable<TItem> _source;

        public CollectionConverter(IEnumerable<TItem> source)
        {
            _source = source;
        }

        public TCollection To<TCollection>()
            where TCollection : ICollection<TItem>, new()
        {
            var collection = new TCollection();
            foreach(var item in _source)
            {
                collection.Add(item);
            }
            return collection;
        }
    }

    public static CollectionConverter<T> Convert<T>(this IEnumerable<T> sequence)
    {
        return new CollectionConverter<T>(sequence);
    }
}

Usage:

customCollectionInstance.OrderBy(i => i.Property).Convert().To<CustomCollection>();
like image 174
max Avatar answered Oct 03 '22 06:10

max