Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# create constructor while running

Tags:

c#

reflection

I started to read about reflection and I wonder, is there a way to create a constructor while the program is running. For example: Get class C and check if C got empty constructor, if not, create on and use it to create this instance. The constructor might have parameters too.

How can I do that? Thank you

like image 914
MyNick Avatar asked Sep 10 '14 13:09

MyNick


2 Answers

In the .NET world, you need to know quite some things.

  1. When a class doens't have a constructor, the compiler adds a default public one without any parameters.

That means that when you have the following class:

public class Person
{
    public int Age
    {
        get { return 10; }
    }
}

It can be instantiated like:

class Program
{
    static void Main(string[] args)
    {
        var person = new Person();
        Console.WriteLine(person.Age);
    }
}

This would produce the following output:

enter image description here

  1. As soon as you create a constructor, the default public, parameterless one is not added by the compiler.

This means that when you change your person class to the following:

public class Person
{
    private Person() { }

    public int Age
    {
        get { return 10; }
    }
}

You're not able to instantiate the class using the new() keyword:

var person = new Person();

This would result in a compile error:

enter image description here

  1. Through reflection, you can construct an object event if the constructor is private and/or does contain parameters.

That being said, your question is unclear because you would never need to create a constructor at runtime, because of the following:

  • A class without a constructor has a constructor added by the compiler and can be constructed through reflection.
  • A class with a constructor can be constructed through reflection.
  • A class with an in-accesible constructed can be constructed through reflection.

Now, let's see how to construct classes using reflection using the 3 scenario's above:

  • You have a class without a constructor.

    public class Person
    {
        public int Age
        {
            get { return 10; }
        }
    }
    

    Your instance can be created like:

    var instance = (Person)Activator.CreateInstance(typeof(Person));
    
  • You have a class with a public constructor

    public class Person
    {
        public Person() { }
    
        public int Age
        {
            get { return 10; }
        }
    }
    

    Your instance can be created just in the same way as above, nothing special is needed.

    var instance = (Person)Activator.CreateInstance(typeof(Person));
    
  • You have a class with a private constructor

    public class Person
    {
        private Person() { }
    
        public int Age
        {
            get { return 10; }
        }
    }
    

    Now your instance cannot be created in such an easy way. First, you need to get your ConstructorInfo:

    ConstructorInfo c = typeof(Person).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] {  }, null);
    

    With the code above, your requesting information about the constructors which are not public (BindingFlags.NonPublic).

    After you have retrieved it, you can construct your object like:

    var instance = (Person)c.Invoke(new object[] { });
    

Let's make it a bit more difficult with the following scenario's:

  • You have a class with a public constructor that accepts parameters:

    public class Person
    {
        public Person(int age)
        {
            Age = age;
        }
    
        public readonly int Age;
    }
    

    The creation is still quite easy:

    var instance = (Person)Activator.CreateInstance(typeof(Person), 15);
    

    You just need to pass all your parameters in the same way as they are defined in your constructor.

  • You have a class with a private constructor that accepts parameters:

    public class Person
    {
        public Person(int age)
        {
            Age = age;
        }
    
        public readonly int Age;
    }
    

    Again, we'll need the ConstructorInfo object, but now we need to specify with types of parameters are constructor is accepting. In the example above, this is an integer:

    ConstructorInfo c = typeof(Person).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(int) }, null);
    

    Now, you can create an object and as a last parameter you specify all the arguments to construct your object.

    var instance = (Person)c.Invoke(new object[] { 15 });
    

So, this was a very long post about reflection but I hope that I mde some things clear. At least, it should be clear right now why you don't need to add a constructor at runtime in able to invoke an object.

like image 122
Complexity Avatar answered Nov 09 '22 22:11

Complexity


You could create a new Type via Reflection.Emit but creating a constructor for existing type is not possible as constructors should be there in metadata of the type in the assembly. You need to declare the constructor upfront.

If you use Mono.Cecil you could add new constructor to a type, then save it in a new assembly(but that's different story).

like image 29
Sriram Sakthivel Avatar answered Nov 09 '22 23:11

Sriram Sakthivel