Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing a Private Constructor from Outside the Class in C#

If I define a class with a private default constructor and a public constructor that has parameters, how can I access the private constructor?

public class Bob
{
   public String Surname { get; set; }

   private Bob()
   { }

   public Bob(string surname)
   {
      Surname = surname;
   }
}

I can access the private constructor via a static method on the class like this:

public static Bob GetBob()
{
   return new Bob();
}

I thought that I could access the private constructor via an extension method, since (according to my understanding) extension methods are translated so that they appear to be static methods on the class, but I can't:

static class Fred
{
   public static Bob Bobby(this Bob bob)
   {
      return new Bob();
   }
}

So, how can I access the private constructor?

Thank you


EDIT:

The reason that I wanted to do this was that I wanted to create tests for one of our business classes, but not allow a consumer of this class to be able to instantiate an object incorrectly. I'm testing it, so I know (I hope!) under what circumstances the tests will fail. I'm still a testing n00b right now so my idea may or may not have been the "wrong way" of doing things.

I've changed my testing strategy to just do things the way the a consumer of this class would, i.e. calling the public methods and if the public methods are OK, assuming that the private methods are OK. I would still prefer to test the private methods, but my boss is breathing down my neck on a deliverable :-(

like image 924
AndrewJacksonZA Avatar asked Nov 12 '10 08:11

AndrewJacksonZA


People also ask

Can we access private constructor outside the class?

A private constructor in Java is used in restricting object creation. It is a special instance constructor used in static member-only classes. If a constructor is declared as private, then its objects are only accessible from within the declared class. You cannot access its objects from outside the constructor class.

How do you call a private constructor from a different class?

Class. getDeclaredConstructor() can be used to obtain the constructor object for the private constructor of the class. The parameter for this method is a Class object array that contains the formal parameter types of the constructor.

Can we call private constructor?

Yes, we can declare a constructor as private. If we declare a constructor as private we are not able to create an object of a class. We can use this private constructor in the Singleton Design Pattern.

How can you use a private constructor?

Private constructors are used to prevent creating instances of a class when there are no instance fields or methods, such as the Math class, or when a method is called to obtain an instance of a class. If all the methods in the class are static, consider making the complete class static.


3 Answers

New answer (nine years later)

There is now several overloads for Activator.CreateInstance that allow you to use non public constructors:

Activator.CreateInstance(typeof(YourClass), true);

true = use non public constructors.

.

Old answer

Default constructors are private for a reason. The developer doesn't make it private for fun.

But if you still want to use the default constructor you get it by using reflection.

var constructor = typeof(Bob).GetConstructor(BindingFlags.NonPublic|BindingFlags.Instance, null, new Type[0], null);
var instance = (Bob)constructor.Invoke(null);

Edit

I saw your comment about testing. Never test protected or private methods / properties. You have probably done something wrong if you can't manage to test those methods/properties through the public API. Either remove them or refactor the class.

Edit 2

Forgot a binding flag.

like image 179
jgauffin Avatar answered Sep 23 '22 01:09

jgauffin


There are several ways around this issue:

One: Make the constructor public. If you need to access it from outside the class why is it private (it might be that you only want to access the private constructor for testing, in which case this is a valid issue).

Two: Make the constructor protected, then access it through a derived class:

public class Bob
{
    public String Surname { get; set; }

    protected Bob()
    { }

    public Bob(string surname)
    {
        Surname = surname;
    }
}

public class Fred : Bob
{
    public Fred()
        : base()
    {
    }
}

Three: Use reflection (as shown by jgauffin).

like image 24
Dr Herbie Avatar answered Sep 24 '22 01:09

Dr Herbie


In additional to @jgauffin's answer which tells how to call private constructors via reflection:

Is it possible to change the modifiers of the private constructor?

It seems that you are implementing Factory Pattern in your code. Thus the modifier is supposed to be internal.

public class Product
{
   //others can't create instances directly outside the assembly
   internal Product() { }    
}
public class ProductProvider
{
   //they can only get standardized products by the provider
   //while you have full control to Product class inside ProductProvider
   public static Product CreateProduct()
   {
       Product p = new Product();    
       //standardize the product
       return p;
   }  
}

Extension methods

public static MyExt
{
   public static void DoSomething(this Product p) { }
}

Calling p.DoSomething() actually equals to MyExt.DoSomething(p). It's not putting this method into class Product.

like image 37
Cheng Chen Avatar answered Sep 24 '22 01:09

Cheng Chen