Purpose of Activator.Createinstance with Example

Purpose of Activator.CreateInstance with example?

Say you have a class called MyFancyObject like this one below:

class MyFancyObject
{
public int A { get;set;}
}

It lets you turn:

String ClassName = "MyFancyObject";

Into

MyFancyObject obj;

Using

obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))

and can then do stuff like:

obj.A = 100;

That's its purpose. It also has many other overloads such as providing a Type instead of the class name in a string. Why you would have a problem like that is a different story. Here's some people who needed it:

  • Createinstance() - Am I doing this right?
  • C# Using Activator.CreateInstance
  • Creating an object without knowing the class name at design time

C# Using Activator.CreateInstance

When using reflection you should ask yourself a couple of questions first, because you may end up in an over-the-top complex solution that's hard to maintain:

  1. Is there a way to solve the problem using genericity or class/interface inheritance?
  2. Can I solve the problem using dynamic invocations (only .NET 4.0 and above)?
  3. Is performance important, i.e. will my reflected method or instantiation call be called once, twice or a million times?
  4. Can I combine technologies to get to a smart but workable/understandable solution?
  5. Am I ok with losing compile time type safety?

Genericity / dynamic

From your description I assume you do not know the types at compile time, you only know they share the interface ICalculation. If this is correct, then number (1) and (2) above are likely not possible in your scenario.

Performance

This is an important question to ask. The overhead of using reflection can impede a more than 400-fold penalty: that slows down even a moderate amount of calls.

The resolution is relatively easy: instead of using Activator.CreateInstance, use a factory method (you already have that), look up the MethodInfo create a delegate, cache it and use the delegate from then on. This yields only a penalty on the first invocation, subsequent invocations have near-native performance.

Combine technologies

A lot is possible here, but I'd really need to know more of your situation to assist in this direction. Often, I end up combining dynamic with generics, with cached reflection. When using information hiding (as is normal in OOP), you may end up with a fast, stable and still well-extensible solution.

Losing compile time type safety

Of the five questions, this is perhaps the most important one to worry about. It is very important to create your own exceptions that give clear information about reflection mistakes. That means: every call to a method, constructor or property based on an input string or otherwise unchecked information must be wrapped in a try/catch. Catch only specific exceptions (as always, I mean: never catch Exception itself).

Focus on TargetException (method does not exist), TargetInvocationException (method exists, but rose an exc. when invoked), TargetParameterCountException, MethodAccessException (not the right privileges, happens a lot in ASP.NET), InvalidOperationException (happens with generic types). You don't always need to try to catch all of them, it depends on the expected input and expected target objects.

To sum it up

Get rid of your Activator.CreateInstance and use MethodInfo to find the factory-create method, and use Delegate.CreateDelegate to create and cache the delegate. Simply store it in a static Dictionary where the key is equal to the class-string in your example code. Below is a quick but not-so-dirty way of doing this safely and without losing too much type safety.

Sample code

public class TestDynamicFactory
{
// static storage
private static Dictionary<string, Func<ICalculate>> InstanceCreateCache = new Dictionary<string, Func<ICalculate>>();

// how to invoke it
static int Main()
{
// invoke it, this is lightning fast and the first-time cache will be arranged
// also, no need to give the full method anymore, just the classname, as we
// use an interface for the rest. Almost full type safety!
ICalculate instanceOfCalculator = this.CreateCachableICalculate("RandomNumber");
int result = instanceOfCalculator.ExecuteCalculation();
}

// searches for the class, initiates it (calls factory method) and returns the instance
// TODO: add a lot of error handling!
ICalculate CreateCachableICalculate(string className)
{
if(!InstanceCreateCache.ContainsKey(className))
{
// get the type (several ways exist, this is an eays one)
Type type = TypeDelegator.GetType("TestDynamicFactory." + className);

// NOTE: this can be tempting, but do NOT use the following, because you cannot
// create a delegate from a ctor and will loose many performance benefits
//ConstructorInfo constructorInfo = type.GetConstructor(Type.EmptyTypes);

// works with public instance/static methods
MethodInfo mi = type.GetMethod("Create");

// the "magic", turn it into a delegate
var createInstanceDelegate = (Func<ICalculate>) Delegate.CreateDelegate(typeof (Func<ICalculate>), mi);

// store for future reference
InstanceCreateCache.Add(className, createInstanceDelegate);
}

return InstanceCreateCache[className].Invoke();

}
}

// example of your ICalculate interface
public interface ICalculate
{
void Initialize();
int ExecuteCalculation();
}

// example of an ICalculate class
public class RandomNumber : ICalculate
{
private static Random _random;

public static RandomNumber Create()
{
var random = new RandomNumber();
random.Initialize();
return random;
}

public void Initialize()
{
_random = new Random(DateTime.Now.Millisecond);
}

public int ExecuteCalculation()
{
return _random.Next();
}
}

How to use Activator.CreateInstance to reflect a type whose constructor parameter differs only by ref

In order to match the ref int x parameter, you can create an instance using Type.GetConstructor and passing it an System.Int32& as a parameter:

var ctor = typeof(SomeType).GetConstructor(new[] { Type.GetType("System.Int32&") });
var constructorParameters = new object[] { 1 };
SomeType someType = (SomeType)ctor.Invoke(constructorParameters);

Edit:

As @mikez suggested, it is even better to use typeof(int).MakeByRefType() instead of System.Int32&:

var ctor = typeof(SomeType).GetConstructor(new[] { typeof(int).MakeByRefType(); });
var constructorParameters = new object[] { 1 };
SomeType someType = (SomeType)ctor.Invoke(constructorParameters);

How can I use Activator.CreateInstance to create a List T 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;
}

Why is Activator.CreateInstance T () 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).

Advantage of Activator.CreateInstance in this scenario

The problem with generics is that you can't define a constraint on a complex constructor. The only constraint is the availability of an empty constructor.

public static T CreateInstance<T>() where T : new()
{
return new T();
}

However, when you want to pass parameter, you'll have to use other methods, such as Activator.CreateInstance. You can also use lambda.

public static T CreateInstance<T>(Func<FormControl, T> builder, FormControl parent)
{
return builder(parent);
}

But you'll have to provide a specific lambda for constructing your object, for each different object.

MyButton b = CreateInstance<MyButton>(parent => new MyButton(parent), SomeformInstance);

By using reflection, you can make code simpler and automatically use a pre-defined constructor. But by using lambda, you can use class that don't match a given convention and fill other constructor arguments with you own data.

var b2 = CreateInstance<MyOtherButton>(
parent => new MyOtherButton("name", 42, parent), SomeformInstance
);

Activator.CreateInstance T Vs new

This overload of the "Activator.CreateInstance" method is used by compilers to implement the instantiation of types specified by type parameters using generics.

Say you have the following method:

public static T Factory<T>() where T: new()
{
return new T();
}

The compiler will convert the "return new T();" to call "CreateInstance".

In general, there is no use for the CreateInstance 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 (new operator in C#, New in Visual Basic, gcnew in C++).

More Info: http://msdn.microsoft.com/en-us/library/0hcyx2kd.aspx



Related Topics



Leave a reply



Submit