112

I have the following scenario:

class Addition{
 public Addition(int a){ a=5; }
 public static int add(int a,int b) {return a+b; }
}

I am calling add in another class by:

string s="add";
typeof(Addition).GetMethod(s).Invoke(null, new object[] {10,12}) //this returns 22

I need a way similar to the above reflection statement to create a new object of type Addition using Addition(int a)

So I have string s= "Addition", I want to create a new object using reflection.

Is this possible?

Markus
  • 3,225
  • 6
  • 35
  • 47
scatman
  • 14,109
  • 22
  • 70
  • 93
  • 3
    Why do you want to use reflection ? Reflection comes with a performance penalty, creates maintenances issues on the long run... – Patrick Peters Jul 15 '10 at 13:03
  • 34
    @Patrick, there are many cases where the performance penalty can be ignored as long as the user goal is achieved. – Kiril Jul 15 '10 at 15:19

2 Answers2

194

I don't think GetMethod will do it, no - but GetConstructor will.

using System;
using System.Reflection;

class Addition
{
    public Addition(int a)
    {
        Console.WriteLine("Constructor called, a={0}", a);
    }
}

class Test
{
    static void Main()
    {
        Type type = typeof(Addition);
        ConstructorInfo ctor = type.GetConstructor(new[] { typeof(int) });
        object instance = ctor.Invoke(new object[] { 10 });
    }
}

EDIT: Yes, Activator.CreateInstance will work too. Use GetConstructor if you want to have more control over things, find out the parameter names etc. Activator.CreateInstance is great if you just want to call the constructor though.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    Yes, but then you have to implement all the overload resolution rules to pick the right constructor. Whereas the runtime will do it for you if you call http://msdn.microsoft.com/en-us/library/wcxyzt4d.aspx – Ben Voigt Jul 15 '10 at 13:02
  • 4
    So `GetConstructor` is preferred if you want to cache a delegate (performance enhancement when calling the same constructor many times), but for one-off use `Activator` would be easier. – Ben Voigt Jul 15 '10 at 13:04
  • @Ben: It definitely depends on your requirements, yes. – Jon Skeet Jul 15 '10 at 13:04
  • Jon Skeet - I want to try this snippet in Vb.NET, but there is a compiler Error in Vb.Net. Error in New[] Error 8 Identifier expected. – Akshay Joy Mar 07 '13 at 06:19
  • @AkshayJoy: Well yes, arrays are initialized using different syntax in VB. Try compiling it in C# and then decompiling it in VB using something like Reflector - or use a C# to VB conversion tool. – Jon Skeet Mar 07 '13 at 06:23
  • 3
    @AkshayJoy: "its ot working" isn't nearly enough information. I've told you how to go about converting it mechanically - another alternative would be to make sure you understand the C# code and then make sure you know the VB syntax for constructing an array. Without wishing to be mean, if that's too much of a challenge then you should really *really* stay away from reflection. – Jon Skeet Mar 07 '13 at 06:48
  • 1
    Got it Thanks Jon Skeet Dim params(0) As Type params(0) = GetType(FViewer) Dim constructorInfoObj As ConstructorInfo = objType.GetConstructor(params) – Akshay Joy Mar 07 '13 at 06:50
  • How do I call the constructor of the base class in case the class Addition doesn't have a constructor? @Jon Skeet – Sarath Subramanian Nov 24 '14 at 12:24
  • 1
    @SarathAvanavu: You wouldn't do that with reflection anyway... it's not clear what situation you're talking about, so it may be worth asking a new question (after searching for similar ones, of course). – Jon Skeet Nov 24 '14 at 12:49
  • K. Thank you :) @Jon Skeet – Sarath Subramanian Nov 25 '14 at 03:35
  • It is also worth pointing out that there is another Invoke overload that allows you to invoke the constructor on a pre-existing instance. I think of the Invoke(Object[] args) as an allocator+initializer and Invoke(Object instance, Object[] args) as just an initializer. – MarkPflug Aug 10 '15 at 21:25
  • Is there anyway to make this line dynamic ` Type type = typeof(Addition);` - I mean I want to put that in a loop – Chandra Shekhar Dec 19 '17 at 11:11
  • @Chandra: Well without knowing any more context, it's hard to help. You could easily create an array or a list and loop over it... – Jon Skeet Dec 19 '17 at 11:49
  • @JonSkeet I solved it after replacing ` Type type = typeof(Addition);` with ` Type type = Type.GetType("ClassName");` – Chandra Shekhar Dec 19 '17 at 12:12
  • 1
    With Activator, you cannot call private constructors, like a singleton class – Efe Jul 16 '19 at 10:14
  • Perfect solution... :) – Umut D. Nov 17 '21 at 18:05
56

Yes, you can use Activator.CreateInstance

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • 2
    This really needs to be a proper answer – Mr. Boy Feb 17 '20 at 18:35
  • Interestingly, it seems that when constructors have parameters, then reflection is faster than Activator.CreateInstance: https://gist.github.com/KallDrexx/d08a60f2d807673af1d9e90e07d61aeb – KallDrexx May 04 '21 at 16:52
  • @KallDrexx: Your benchmark is not measuring the cost of reflection correctly, because most of it is being done outside the measured function. Move the `typeof(Program).GetConstructor(new[] {typeof(int)});` inside the function that calls it to have a fairer comparison. And even then, you have chosen the exact matching overload ahead of time, while `Activator` has to do overload resolution across all constructors with the same number of parameters. – Ben Voigt May 04 '21 at 17:59
  • @BenVoigt while true, if you refresh you will see a new test where I did add this test case. Even with considering the timing of `GetConstructor()` call it still is 2/3rds the time of an ACtivator.CreateInstance. I also don't think it's unreasonable for Activator.CreateInstance to cache any reflection calls it may incur (since it's reasonable it may be called again) but whatever its cost is it apparently doesn't. – KallDrexx May 05 '21 at 14:20