Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create instance of a parameterized generic object with all parameters set to null

Assume a class with a parameterized constructor as:

MyObject(string param1, string param2, string param2)
{
   ...
}

I have a Generic method that returns an instance of the Generic Class and MyObject is one of such instances.

How can I instantiate a generic class with a parameterized constructor and pass null values to all its parameters? This is needed as properties of the generic class get populated at a slightly later stage.

I have tried using Activator as:

public static T GetGenericObject<T>()
{
   T resource = (T)Activator.CreateInstance(typeof(T), null); 
   ... 
}

But I get exception that I got no parameterless constructor in MyObject. I know I could add one easily but the class cannot be modified (don't ask why).

like image 846
eYe Avatar asked Jul 10 '15 19:07

eYe


People also ask

Can you create instances of generic type parameters?

Constructing an Instance of a Generic Type A generic type is like a template. You cannot create instances of it unless you specify real types for its generic type parameters. To do this at run time, using reflection, requires the MakeGenericType method.

What is activator CreateInstance in C#?

The Activator. CreateInstance method creates an instance of a type defined in an assembly by invoking the constructor that best matches the specified arguments. If no arguments are specified then the constructor that takes no parameters, that is, the default constructor, is invoked.


2 Answers

You could detect how many parameters there are via reflection, and then pass in null values for each of them in Activator.CreateInstance():

var parameters = typeof(T)
    .GetConstructors()
    .Single()
    .GetParameters()
    .Select(p => (object)null)
    .ToArray();
T resource = (T)Activator.CreateInstance(typeof(T), parameters); 

Note that this assumes there's only one constructor, and it'll only work for reference types, so it's fairly fragile.

like image 116
StriplingWarrior Avatar answered Sep 29 '22 06:09

StriplingWarrior


Use the overload that takes parameters and create an object array to pass where null represents each needed parameter.

In light of your comment, you can certainly tell the method to create an initialized but empty object array based on a fixed number of elements. However, as mentioned in other comments, this is extremely dangerous and will cause you headaches down the road.

var instance = GetGenericObject<MyObject>(3);

public static T GetGenericObject<T>(int numberOfNullParametersToPass)
{
    var nullParams = new object[numberOfNullParametersToPass];
    T resource = (T)Activator.CreateInstance(typeof(T), nullParams); 
    return resource;
}

As your code currently stands, you are explicitly telling Activator.CreateInstance to choose the parameterless constructor. By specifying all three arguments (even though they are null), you are selecting the correct constructor.

At some point in the call chain you need to tell Activator.CreateInstance which constructor to choose. An alternative is to choose the first possible constructor.

public static T GetGenericObject<T>()
{
    var paramLength = typeof(T).GetConstructors().FirstOrDefault().GetParameters().Length;
    var parameters = new object[paramLength]; 
    T resource = (T)Activator.CreateInstance(typeof(T), parameters); 
    return resource;
}
like image 36
David L Avatar answered Sep 29 '22 05:09

David L