Create Instance of Generic Type Whose Constructor Requires a Parameter

Create instance of generic type whose constructor requires a parameter?

Additionally a simpler example:

return (T)Activator.CreateInstance(typeof(T), new object[] { weight });

Note that using the new() constraint on T is only to make the compiler check for a public parameterless constructor at compile time, the actual code used to create the type is the Activator class.

You will need to ensure yourself regarding the specific constructor existing, and this kind of requirement may be a code smell (or rather something you should just try to avoid in the current version on c#).

How to create an instance of generic type whose constructor requires a delegate function parameter?

Constructing a delegate of an unknown type dynamically isn't as easy as using reflection to call a method, so the easiest option is to just write a statically typed method to construct the delegate, and then just call it using reflection.

public class DelegateCreator
{
public static Func<T> MakeConstructorStatically<T>()
{
return Activator.CreateInstance<T>;
}

public static object MakeConstructorDynamically(Type type)
{
return typeof(DelegateCreator)
.GetMethod(nameof(MakeConstructorStatically))
.MakeGenericMethod(type)
.Invoke(null, Array.Empty<object>());
}
}

Create Instance of Generic Type

You should use: CreateInstance(typeof(T)), typeof returns an object of class System.Type which will work.

There is a difference in C# between a 'Generic' type T and an instance of System.Type. Activator.CreateInstance requires the latter.


Edit: You should generally use DavidG's method, it is cleaner. You can use the Activator when:

  • You can't add a generic constraint for some reason.
  • You want to pass arguments to the constructor. (the new() constraint implies a parameterless constructor, with the Activator you can pass parameters.)

Create instance of generic class with dynamic generic type parameter

I found very simple solution to problem. There is no need to cast object to specific type T, just use dynamic keyword instead of casting

   Type myGeneric = typeof(MyComparer<>);
Type constructedClass = myGeneric.MakeGenericType(T);
object created = Activator.CreateInstance(constructedClass);
dynamic comparer = created; // No need to cast created object to T

and then I can use comparer normally to call its methods like:

   return comparer.Equals(myResultAsT, correctResultAsT);

According to LueTm comments, it is probably possible to use reflection again and call comparer methods, but this solution looks much easier.

Create instance of a generic type that takes a parameter a secondary generic type

After Abion47 pointed out that Activator.CreateInstance shouldn't have any issues doing what I need it to do I looked a bit more into the issue and made it work.

For anyone that might come across this:

public abstract class Sentinel<T,U> where T: new() where U: new() 
{
public T CreateModel(IDictionary<String, Object> parametersDictionary)
{
T toReturn ;

if (ValidateDictionary(parametersDictionary) != true)
return default(T);
else
{
U parameters = ParseDictionaryToParameters(parametersDictionary);
toReturn = (T)Activator.CreateInstance(typeof(T), new object[] {parameters});
}

//If we got this far then everything should be fine.
return toReturn;
}

public abstract U ParseDictionaryToParameters(IDictionary<String, Object> parametersDictionary);

public abstract Boolean ValidateDictionary(IDictionary<String, Object> parametersDictionary);
}

Create instance of class with generic type and call method of same generic type from string name of object at runtime

Your wrapper got the following signature:

public class MyClass<T> where T : class, new()

it basically says "T needs to be a class and have a default constructor". The interesting part is about the default constructor. It means that the class must have a constructor with no arguments.

It tells .NET that you can invoke:

var obj = new T();

So the first step is to do just that:

public class MyClass<T> where T : class, new()
{
public IList<T> MyMethod(Stream stream)
{
var data = new List<T>();

//this
var obj = new T();

return data;
}
}

next you wanted to invoke a method. That's done with the help of reflection.

A simple example is:

var obj = new T();

//get type information
var type = obj.GetType();

//find a public method named "DoStuff"
var method = type.GetMethod("DoStuff");

// It got one argument which is a string.
// .. so invoke instance **obj** with a string argument
method.Invoke(obj, new object[]{"a string argument"});

Update

I missed the important part:

I need to return my IList from the MyMethod() method based on the name of the object I'm passing in as a string.

If the type is declared in the same assembly as your executing code you can just pass the full type name like Some.Namespace.ClassName" toType.GetType()`:

var type = Type.GetType("Some.Namespace.ClassName");
var obj = Activator.CreateInstance(type);

If the class is declared in another assembly you need to specify it:

var type = Type.GetType("Some.Namespace.ClassName, SomeAsseblyName");
var obj = Activator.CreateInstance(type);

The rest is pretty much the same.

If you only have the class name you can traverse the assembly to find the correct type:

var type = Assembly.GetExecutingAssembly()
.GetTypes()
.FirstOrDefault(x => x.Name == "YourName");
var obj = Activator.CreateInstance(type);

Issue activating a generic type with generic array in constructor parameters

I can tell you what happens. Having a look at the resulting assembly you can see that the compiler introduces an object[] wrapping the values argument:

Activator.CreateInstance(specificType, new string[] { "foo", "bar" });
Activator.CreateInstance(specificType, new object[] { values });

Now the right overload can not be found anymore.
If you add a cast you will get the expected result and the code works again:

Activator.CreateInstance(specificType, values as string[])

But i can not tell you why this happens, maybe it can be digged out of the specs.



Related Topics



Leave a reply



Submit