1

I have a base class with many descendants. In the base class a parameter-less constructor is declared. Descendants may declare specialized constructors.

public class A 
{
   public A()
   {
   }
}

public class B : A
{
  string Stuff { get; set; }
  public B(string stuff)
  {
    Stuff = stuff;
  }
}

At some point I want to instantiate a B using the Activator. This instance needs no initialization of it's "Stuff". So I want to use the A's default constructor:

public object InstantiateType(Type type)
{
   return Activator.CreateInstance(
      type,
      BindingFlags.CreateInstance |
      BindingFlags.Public |
      BindingFlags.NonPublic
   );
}

This sample call results in an exception as many other variations on this theme, is it at all possible, and if so how do I instruct the Activator to do so?

Binkan Salaryman
  • 3,008
  • 1
  • 17
  • 29
k.c.
  • 1,755
  • 1
  • 29
  • 53

2 Answers2

3

At some point I want to instantiate a B using ... A's default constructor

You can't. Constructors aren't inherited, and there is no parameterless constructor for B that you can use. You will need to create a constructur that passes through to the base constructor:

public class B : A
{
  string Stuff{get;set}
  public B(string stuff)
  {
    Stuff = stuff;
  }
  public B() : base()  // technically the ": base()" is redundant since A only has one constructor
  {
  }
}

You could also change your CreateInstance call to pass in null as the string parameter.

D Stanley
  • 149,601
  • 11
  • 178
  • 240
2

Here is a workaround for you:

public class A {
    ///<summary>Creates an instance of A, or of a subclass of A</summary>
    public static A Create<T>() where T : A {
        A result = (A)FormatterServices.GetUninitializedObject(typeof(T));
        result.defaultInit();
        return result;
    }

    public A() {
        defaultInit();
    }

    private void defaultInit() {
        // field assignments ...
        // default constructor code ...
    }
}

public class B : A {
    string Stuff { get; set; }
    public B(string stuff) {
        Stuff = stuff;
    }
}
Binkan Salaryman
  • 3,008
  • 1
  • 17
  • 29
  • 1
    I will try this, as the default constructor doesn't perform any work, If it works the green tick is for you – k.c. Mar 26 '15 at 15:27
  • It works even without the default init. I needed an instance to invoke a method that builds some delegates. No data is used. For normal use it would not be very safe according to the documentation, and implementing a defaultinit in each class would be no better than adding a constructor, but for this your out of the box answer is great! – k.c. Mar 26 '15 at 15:39