locked
Calling private constructor in derived class RRS feed

  • Question

  • User-1796506859 posted

    Hi Folks,

     I have a couple of classes in a simple console app - in the base class I have a static Create method which is to instantiate a derived class and return its instance.  I want to make the constructor in the derived class private.  The constructor takes no parameters (are void).

    public class BaseClass {
       public static Create() {
           ConstructorInfo ci = typeof(DerivedClass).GetConstructor(BindingFlags.NonPublic | BindingFlags.CreateInstance, null, Type.EmptyTypes, null);  // ci is null
           ConstructorInfo ci = typeof(DerivedClass).GetConstructor(BindingFlags.NonPublic | BindingFlags.CreateInstance, null, new Type[] { typeof(String) }, null); // ci is null
    
    }
    
    public class DerivedClass : BaseClass {
       private DerivedClass() {}
       private DerivedClass(String data) {}
    }
    
    

    If I change the constructors to both be public and call  GetConstructors() to return the list of constructors, I can see both of them in the list returned. However, if I change the above GetConstructor() calls to use BindingFlags.Public, I still get null returned.

    Does anyone have any ideas on why it may not be working ?

    Monday, June 18, 2018 2:22 AM

All replies

  • User303363814 posted

    I want to make the constructor in the derived class private

    This means that you do not want it to be accessible from the containing class.  But then you want to access it?  The two decisions contradict each other.

    It is not really clear what you are trying to do.  Do you want something like https://www.dotnetperls.com/factory ? 

    (or in more depth https://www.dotnettricks.com/learn/designpatterns/factory-method-design-pattern-dotnet )

    PS - Free advice (worth what you pay for it) do not use reflection unless you absolutely, positively, 100% do not have any alternative)

    Tuesday, June 19, 2018 12:01 AM
  • User36583972 posted


    Hi AndyW2009,

    If I change the constructors to both be public and call  GetConstructors() to return the list of constructors, I can see both of them in the list returned. However, if I change the above GetConstructor() calls to use BindingFlags.Public, I still get null returned.

    Does anyone have any ideas on why it may not be working ?

    You can try the following code.

      public class DerivedClass : BaseClass
        {
            private DerivedClass() { }
            private DerivedClass(String data) { }
        }
    
        public class BaseClass
        {
            public static List<ConstructorInfo> Create()
            {
    
                Type myType = typeof(DerivedClass);
                Type[] types = new Type[1];
                types[0] = typeof(string);
                // Get the public instance constructor that has string parameter.
                ConstructorInfo ci = myType.GetConstructor(
                    BindingFlags.Instance | BindingFlags.NonPublic, null,
                    CallingConventions.HasThis, types, null);
    
                ConstructorInfo ci2 = myType.GetConstructor(
                  BindingFlags.Instance | BindingFlags.NonPublic, null,
                  CallingConventions.HasThis, Type.EmptyTypes, null);
    
                //ConstructorInfo ci = typeof(DerivedClass).GetConstructor(BindingFlags.NonPublic | BindingFlags.CreateInstance, null, Type.EmptyTypes, null);  // ci is null
                //ConstructorInfo ci2 = typeof(DerivedClass).GetConstructor(BindingFlags.NonPublic | BindingFlags.CreateInstance, null, new Type[] { typeof(String) }, null); // ci is null
    
                List<ConstructorInfo> ls = new List<ConstructorInfo>();
                ls.Add(ci);
                ls.Add(ci2);
                return ls;
            }
    
    
        }

    For more detialed, please see:ConstructorInfo Class
    https://msdn.microsoft.com/en-us/library/system.reflection.constructorinfo(v=vs.110).aspx

    Best Regards,

    Yong Lu

    Tuesday, June 19, 2018 5:35 AM