Search code examples
c#instantiationactivator

Dynamically instantiate class


I am trying to dynamically instantiate classes descendant of an abstract class, but the activator is forcing me to override the constructor to every descendant. Is there a way to avoid this?

P.S: I need to pass the parameters in the constructor, only there it can be Write, otherwise, it will always be read!


Solution

  • Constructors are not inherited, so if you must instantiate a child object through a constructor with those parameters, then you need to write a new constructor in the child class that basically does base(p1, p2, ..., pn).

    Looking at your code, seems that your constructors only assign/initialize fields, so there is no reason why you can't do that somewhere outside the constructor, as long as you control it appropriately. This might be a long shot, but I feel this is more what you want:

    public abstract class Parent
    {
        protected bool foo
        {
            get;
            private set; // just set the property setter as private
        }
    
        protected Parent() {
            // protected so all instances are created through createAnotherX
            // note that nothing is initialized here!
        }
    
        public abstract int Enter(); // To override in child classes
    
        // Option 1: use generics
        public static T createAnother1<T>(bool f) where T : Parent, new()
        {
            T p = new T();
            p.foo = f;
    
            return p;
        }
        // Option 2: use the runtime type
        public static Parent createAnother2(Type t, bool f)
        {
            Parent p = Activator.CreateInstance(t) as Parent;
            p.foo = f;
    
            return p;
        }
    
        // Examples
        public static void Main()
        {
            Parent p1 = Parent.createAnother1<Child>(true);
            Parent p2 = Parent.createAnother2(typeof(Child), true);
        }
    }
    // the child class only has to worry about overriding Enter()
    public class Child : Parent
    {
        public override int Enter()
        {
            return 1;
        }
    }
    

    Note that you must instantiate objects through the createAnotherX because the default constructor is protected. In addition, as per your comment, see that the property is defined so that only you can set values, which is what you tried to do in your code when explicitly ignoring the setter.