2017-02-04

Polymorphism with interfaces

Howdy,
I recently ran into a need to perform polymorphism through an interface in C# 4.5.2. The wrinkle to this is that each implementation of the interface must have ta common signature for a constructor. Here's the how:

namespace generictrial01
{
    class Program
    {

        static void Main(string[] args)
        {
            AnyGoopWillDo agwd = new AnyGoopWillDo();
            AnyGoopWillDo agwd_1 = new AnyGoopWillDo(typeof(SpecialGoop));
            AnyGoopWillDo agwd_2 = new AnyGoopWillDo(typeof(NormalGoop));

            Console.WriteLine("default constructor");
            agwd.DoingTheObvious();
            Console.WriteLine("parameterized constructor - special");
            agwd_1.DoingTheObvious();
            Console.WriteLine("parameterized constructor - normal");
            agwd_2.DoingTheObvious();

            int i = 9;  // used as a breakpoint
        }

        /*
            Expected output:
                default constructor
                NormalGoop says "wow"
                parameterized constructor - special
                SpecialGoop says "yuck"
                parameterized constructor - normal
                NormalGoop says "wow"
        */
    }

    public interface IGoop
    {
        void PerformMiracle();
    }

    public class NormalGoop : IGoop
    {
        private string GoopString { get; set; }

        public NormalGoop()
        {
            GoopString = "wow";
        }

        public void PerformMiracle()
        {
            Console.WriteLine("NormalGoop says \"{0}\"", GoopString);
        }
    }

    public class SpecialGoop : IGoop
    {
        public void PerformMiracle()
        {
            Console.WriteLine("SpecialGoop says \"yuck\"");
        }
    }

    public class AnyGoopWillDo
    {
        private readonly Type _goopish;

        public AnyGoopWillDo()
        {
            _goopish = typeof(NormalGoop);
        }

        public AnyGoopWillDo(Type initType)
        {
            _goopish = initType;
        }

        public void DoingTheObvious()
        {
            UsingGoop test = new UsingGoop(_goopish);
            test.UseThisGoop();
        }
    }

    public class UsingGoop
    {
        private Type TheType { get; set; }

        public UsingGoop(Type initType)
        {
            TheType = initType;
        }
        public void UseThisGoop()
        {
            // this will determine if initType implements IGoop
            // see http://stackoverflow.com/questions/15138924/c-sharp-how-to-determine-if-a-type-implements-a-given-interface
            if (typeof (IGoop).IsAssignableFrom(TheType.UnderlyingSystemType))
            {
                IGoop iGoop = (IGoop) Activator.CreateInstance(TheType);
                iGoop.PerformMiracle();
            }
        }
    }
}