John Liu .NET

View Original

Get it and Do something with it.

I wrote a much better version of the Get & Do that I'm happy with.  Here's the code below.



// Using this:

private void Form1_Load(object sender, EventArgs e)

{

    new Get<Control>(this.button1, this.button2, this.button3, this.button4)

        .Do(delegate(Control c) { c.Enabled = false; return c; })

        .Do(delegate(Control c) { c.BackColor = Color.Red; return c; });



    new Get<Control>(this.Controls)

        .Do(delegate(Control c) { c.Visible = false; return c; });

}



// The Get class below.

using System.Collections;

using System.Collections.Generic;

namespace GetAndDo
{
    /// <summary>
    /// Get something we want
    /// </summary>
    /// <typeparam name="T"></typeparam>
    class Get<T>
    {
        public List<T> objects;

        /// <summary>
        /// Create a Get wrapper around something we want
        /// </summary>
        /// <param name="getObjs">param array of stuff</param>
        /// <remarks>
        /// Try to design the constructor to be functional and readable.
        /// </remarks>
        public Get(params object[] getObjs)
        {
            objects = new List<T>();
            foreach (object obj in getObjs)
            {
                if (obj is IEnumerable<T>)
                {
                    objects.AddRange((IEnumerable<T>)obj);
                    continue;
                }
                if (obj is IEnumerable)
                {
                    foreach (object obj1 in (IEnumerable)obj)
                    {
                        if (obj1 is T)
                        {
                            objects.Add((T)obj1);
                        }
                    }
                }
                if (obj is T)
                {
                    objects.Add((T)obj);
                }
            }
        }

        /// <summary>
        /// Signature of a delegate for any actions
        /// </summary>
        /// <param name="obj"></param>
        /// <returns>
        /// null - filter from result set (filter-operation)
        /// true - include obj in result set
        /// T - include new object in result set (map-operation)
        /// IEnumerable - useful for nesting deep
        /// </returns>
        public delegate object Action(T obj);

        /// <summary>
        /// Run delegate on each element in the current Get wrapper
        /// </summary>
        /// <param name="action">delegate to run</param>
        /// <returns>
        /// New Get wrapper - does not modify original wrapper.
        /// This allows chaining of delegates
        /// </returns>
        public Get<T> Do(Action action)
        {
            List<T> newObjects = new List<T>();
            for (int i = 0; i < objects.Count; i++)
            {
                object result = action(objects[i]);
                if (result == null)
                {
                    continue;
                }
                if (result is T)
                {
                    newObjects.Add((T)result);
                    continue;
                }
                if (result is IEnumerable<T>)
                {
                    newObjects.AddRange((IEnumerable<T>)result);
                }
                if (result is IEnumerable)
                {
                    foreach (object obj1 in (IEnumerable)result)
                    {
                        if (obj1 is T)
                        {
                            objects.Add((T)obj1);
                        }
                    }
                }
                if (true.Equals(result))
                {
                    newObjects.Add(objects[i]);
                    continue;
                }
            }
            return new Get<T>(newObjects.ToArray());
        }
    }
}