How to Pass Parameters to Activator.Createinstance<T>()

How to Pass Parameters to Activator.CreateInstanceT()

Yes.

(T)Activator.CreateInstance(typeof(T), param1, param2);

Activator.CreateInstance pass variable to form

You should cast to Form2, not to Form.

I don't know where is problem (if you cast to correct type), but if you have corresponding constructor, your code works fine for me.

You can try to pass arguments as object[](object array) - CreateInstance(Type type, object[] args), but also you can pass arguments by the way you pass them (because method accepts params object[] args).

Try to replace this line:

var obj = (Form)Activator.CreateInstance(Type.GetType("myproject.Form2"),1,"test");

by this:

var obj = 
(Form2)Activator.CreateInstance(Type.GetType("myproject.Form2"), new object[] {1, "test"});

Also, you can use typeof to get Type instance:

var obj = (Form2)Activator.CreateInstance(typeof(Form2), new object[] {1, "test"});

But if you know which type of instance to create at compile time, you should simply create your object using new:

var obj = new Form2(1, "test");

How can I use Activator.CreateInstance to create a ListT where T is unknown at runtime?

Use this approach:

class Program
{
static void Main(string[] args)
{
CreateListFromType(typeof(Foo));
CreateListFromType(typeof(int));
}

static object CreateListFromType(Type t)
{
// Create an array of the required type
Array values = Array.CreateInstance(t, 50);

// and fill it with values of the required type
for (int i = 0; i < 50; i++)
{
values.SetValue(CreateFooFromType(t), i);
}

// Create a list of the required type, passing the values to the constructor
Type genericListType = typeof(List<>);
Type concreteListType = genericListType.MakeGenericType(t);

object list = Activator.CreateInstance(concreteListType, new object[] { values });

// DO something with list which is now an List<t> filled with 50 ts
return list;
}

// Create a value of the required type
static object CreateFooFromType(Type t)
{
return Activator.CreateInstance(t);
}
}

class Foo
{
public Foo() { }
}

There is no need to use dynamic in this case. We can just use object for the value we create. Non-Reference types will be stored in the object using boxing.

In order to create the List<> type, we can first get a representation of the generic type and then use that to create the concrete type using the MakeGenericType method.

Note the mistake you made in the CreateInstance call to create the list:

When trying to construct the list, you need to embed your values array as an element in an array of object. So that Activator will look for a constructor in List<t> that expects a single parameter of type IEnumerable<t>.

The way you have written it, the Activator looks for a constructor which expects 50 arguments, each of type t.


A shorter version using non-generic IList interface

using System.Collections;

static IList CreateListFromType(Type t)
{
// Create a list of the required type and cast to IList
Type genericListType = typeof(List<>);
Type concreteListType = genericListType.MakeGenericType(t);
IList list = Activator.CreateInstance(concreteListType) as IList;

// Add values
for (int i = 0; i < 50; i++)
{
list.Add(CreateFooFromType(t));
}

// DO something with list which is now an List<t> filled with 50 ts
return list;
}

Getting closer to the actual use case: Dynamic List Type

static void Main(string[] args)
{
CreateListFromType(typeof(List<Foo>));
CreateListFromType(typeof(ObservableCollection<int>));
}

static IList CreateListFromType(Type listType)
{
// Check we have a type that implements IList
Type iListType = typeof(IList);
if (!listType.GetInterfaces().Contains(iListType))
{
throw new ArgumentException("No IList", nameof(listType));
}

// Check we have a a generic type parameter and get it
Type elementType = listType.GenericTypeArguments.FirstOrDefault();
if (elementType == null)
{
throw new ArgumentException("No Element Type", nameof(listType));
}

// Create a list of the required type and cast to IList
IList list = Activator.CreateInstance(listType) as IList;

// Add values
for (int i = 0; i < 50; i++)
{
list.Add(CreateFooFromType(elementType));
}

// DO something with list which is now a filled object of type listType
return list;
}

Activator.CreateInstance with param - constructor of child class type not found

Activator.CreateInstance takes a nonPublic parameter only in the case of default constructor invocation.

You can use Type.GetConstructor instead:

Type contextFactoryType = 
Type.GetType("Media.DB.Context.Implementation." + Settings.ContextFactory);

ConstructorInfo ci = contextFactoryType .GetConstructor(
BindingFlags.Instance | BindingFlags.NonPublic,
binder: null, new Type[] { typeof(string) }, modifiers: null);

object[] args = new object[] { connString };

var instance = (BaseContext<DbContext> instance)ci.Invoke(args);
return instance;

Pass arguments as well as string into Activator.CreateInstance

Just pass them in as the 2nd argument.

IFile file = (IFile)Activator.CreateInstance(
Type.GetType("FileParser.File" + args[0]), new object[] { args });

EDIT: Wrapped the 2nd argument in an array as this is the parameter type expected, as well as the argument type on Activator.CreateInstance, I think this is why it is confusing.

Why is Activator.CreateInstanceT() allowed without the new() generic type constraint?

There is a conceptual difference between Activator and T():

  • Activator.CreateInstance<T> — I want to create a new instance of T using its default constructor — And throw an Exception if it doesn't have one (Since something very wrong has happened and I want to handle it/throw it myself).

    • Side note: keep in mind that as MSDN says:

      In general, there is no use for the CreateInstance<T>() generic method in application code, because the type must be known at compile time. If the type is known at compile time, normal instantiation syntax can be used.

      since generally you would want to use a constructor when the Type is known at compile time (CreateInstance<T>() uses RuntimeTypeHandle.CreateInstance which is slower [Also that's why Activator.CreateInstance<T> itself doesn't need the constraint]).

  • T() — I Want to call the empty constructor of T, supposedly like a standard constructor call.

You don't want a "standard" constructor call to fail because "No such constructor was found", therefore, the compiler wants you to constraint that there is one.

More than that; You should prefer Compile time errors over Exceptions where possible.

The fact that T() is implemented internally using reflection irrelevant for the average case of "I just want a default instance of T" (of course that the internal implementation is important if you care about performance/etc...).

Activator.CreateInstance with dynamic Type

There are a using difference... When you write:

var obj = Activator.CreateInstance<myType>();

You used your Class like a Type, and it's the good way to do it.
You used a generic type who have a reference to a class type.

But there:

var obj2 =(myType) Activator.CreateInstance(myType);

You used you class like an instance (object). And you can't do that, a class is a schema.
If you want to call the second method, you have to write:

var obj2 =(myType) Activator.CreateInstance(typeof(myType));

This code will create an instance of the class Type, and this instance will describe your class myType.

I hope to be clear.

A class is a schema, you can create an object with this schema, it will be an instance (a memory-object of your class).

Can't Find Constructor on Generic Class Activator

Activator.CreateInstance() only looks for public constructors by default. If you want to look for other scopes of constructor, you need to use the overload with BindingFlags.

The flags needed are:

const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;

You probably also want to use InvariantCulture, so the overall call would look something like:

return Activator.CreateInstance(type, flags, null, new object[] {myArgs}, CultureInfo.InvariantCulture;)


Related Topics



Leave a reply



Submit