Search code examples
c#constructorprotectedexplicitactivator

Is it possible to CreateInstance of object with protected constructor?


Greetings fellow members, the situation in question is such:

public abstract class BaseClass
{
    protected BaseClass()
    {
        // some logic here
    }

    protected BaseClass(Object parameter) : this()
    {
        // some more logic
    }
}

public class Descendant : BaseClass
{
   // no constructors
}

I'm trying to call Activator.CreateInstance on the Descendant class, but no constructor is found.

Do I need to explicitly define it on the Descentant class?

The bindings I've used are these: BindingFlags.Instance | BindingFlags.NonPublic

Note 1: I'm calling AppDomain.CreateInstanceAndUnwrap() in reality, if it should have some influence.

 domain.CreateInstanceAndUnwrap(path, typeName, false, BindingFlags.Instance |
     BindingFlags.NonPublic, null, new[] { parameter }, null, null);

Note 2: If I explicitly define the protected constructor in the Descendant class then it works, but I'd like to avoid this if possible.


Solution

  • You cannot use Activator.CreateInstance, but in Full Trust environments you should be able to locate and call the constructor directly by reflection.

    Actually, your Descendant class automatically provides a public constructor that does a pass-through to the protected constructor of the base class. This should work just fine:

    Activator.CreateInstance(typeof(Descendant))
    

    Okay, so now I realize that you're trying to invoke the non-default constructor. Unfortunately for you, this is simply not allowed. Invoking the constructor on the base class directly won't work because the base class is abstract. You need to have a constructor (either auto-generated or explicitly defined) on the descendant class in order to construct an object.

    You could create a pass-through constructor on the Descendant class, but your comments make it sound like you're trying to avoid forcing implementers to pass a value through in their constructor. What you probably really want is an initialization method that you can call after constructing the object:

    // Define other methods and classes here
    public abstract class BaseClass
    {
        protected BaseClass()
        {
            // some logic here
        }
    
        protected Object Parameter {get; private set;}    
    
        public virtual void Initialize(Object parameter)
        {
            Parameter = _parameter;
            // some more logic
        }
    }