Creating generic variables from a type - How? Or use Activator.CreateInstance() with properties { } instead of parameters ( )?
Asked Answered
G

3

6

I'm currently using Generics to make some dynamic methods, like creating an object and filling the properties with values.

Is there any way to "dynamically" create the Generic without knowing the type? For example:

List<String> = new List<String>()

is a predefinied way, but

List<(object.GetType())> = new List<(object.GetType()>()

isn't working... But can it?

This isn't working (Is there a similiar approach that works?)

    public T CreateObject<T>(Hashtable values)
    {
        // If it has parameterless constructor (I check this beforehand)
        T obj = (T)Activator.CreateInstance(typeof(T));

        foreach (System.Reflection.PropertyInfo p in typeof(T).GetProperties())
        {
            // Specifically this doesn't work
            var propertyValue = (p.PropertyType)values[p.Name];
            // Should work if T2 is generic
            // var propertyValue = (T2)values[p.Name];

            obj.GetType().GetProperty(p.Name).SetValue(obj, propertyValue, null);
        }
    }

So, in short: how to take a "Type" and create an object from that without using Generics? I have only used Generics in methods so far, but is it possible to use the same way on variables? I have to define a Generic (T) before the method, so can I do the same on variables before "creating" them?

...or how to use "Activator" to create an object with Properties instead of Parameters. Like you do here:

// With parameters values

Test t = new Test("Argument1", Argument2);

// With properties

Test t = new Test { Argument1 = "Hello", Argument2 = 123 };
Gibbons answered 22/5, 2012 at 19:38 Comment(0)
C
13

You can use MakeGenericType:

Type openListType = typeof(List<>);
Type genericListType = openListType.MakeGenericType(obj.GetType());
object instance = Activator.CreateInstance(genericListType);
Carmelo answered 22/5, 2012 at 19:44 Comment(2)
I don't want to use "List" in this case, it should be any object. The "Type openListType = typeof(unknown type);"Gibbons
I don't see how this answer solves the OP "use Activator.CreateInstance() with properties { } instead of parameters ( ) ?"Snippy
B
6

You can use the MakeGenericType method to get the generic type for a particular type argument:

var myObjListType = typeof(List<>).MakeGenericType(myObject.GetType());
var myObj = Activator.CreateInstance(myObjListType);
// MyObj will be an Object variable whose instance is a List<type of myObject>
Bengurion answered 22/5, 2012 at 19:44 Comment(2)
But say the object I create is a "String, boolean, int, float..." not necessarily a class. If I then need to set a value to it before setting the objects property to the value.Gibbons
For value types you don't need to set a value- they automatically have a valid default. For example, a field of type bool doesn't need to be initialized to false, because that happens automatically. For strings, they start out null. If you want to make them to have another value, like "Fred", you need to set their value to "Fred". Not Person.FirstName = new String("Fred");, see?Bengurion
K
1

When you use the object initializer, it's just using a default constructor (no parameters), then setting the individual properties after the object is constructed.

The code above is close - but var won't work here, since it's just a compile-time type inferrence. Since you're already using reflection, you can just use System.Object:

object propertyValue = values[p.Name];

The SetValue call will work fine with System.Object.

Keifer answered 22/5, 2012 at 19:41 Comment(4)
So how can I use Activator.CreateInstance with "Object initializer" as argument? I get an error stating "No parameterless constructor definied for this object." Types of the properties that I try to add values to are: String, Double, enum, bool. The type it fails on is "String". It has no parameterless constructor so I can't create a String and add value to it, but how can that be since I can define: String str; or String str = "This is a string";Gibbons
@Gibbons The type you're generating doesn't have a parameterless constructor - so you can't use this technique with it...Keifer
The String str = "Foo"; syntax is a C# language feature, not a CLR feature.Keifer
...and the tags for my question include "C#".Gibbons

© 2022 - 2024 — McMap. All rights reserved.