Purpose of Activator.CreateInstance with example?

C#.NetReflection

C# Problem Overview


Can someone explain Activator.CreateInstance() purpose in detail?

C# Solutions


Solution 1 - C#

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:

Solution 2 - C#

Well i can give you an example why to use something like that. Think of a game where you want to store your level and enemies in an XML file. When you parse this file, you might have an element like this.

<Enemy X="10" Y="100" Type="MyGame.OrcGuard"/>

what you can do now is, create dynamically the objects found in your level file.

foreach(XmlNode node in doc)
   var enemy = Activator.CreateInstance(null, node.Attributes["Type"]);

This is very useful, for building dynamic enviroments. Of course its also possible to use this for Plugin or addin scenarios and alot more.

Solution 3 - C#

My good friend MSDN can explain it to you, with an example

Here is the code in case the link or content changes in the future:

using System;

class DynamicInstanceList
{
	private static string instanceSpec = "System.EventArgs;System.Random;" +
		"System.Exception;System.Object;System.Version";

	public static void Main()
	{
		string[] instances = instanceSpec.Split(';');
		Array instlist = Array.CreateInstance(typeof(object), instances.Length);
		object item;
		for (int i = 0; i < instances.Length; i++)
		{
			// create the object from the specification string
			Console.WriteLine("Creating instance of: {0}", instances[i]);
			item = Activator.CreateInstance(Type.GetType(instances[i]));
			instlist.SetValue(item, i);
		}
		Console.WriteLine("\nObjects and their default values:\n");
		foreach (object o in instlist)
		{
			Console.WriteLine("Type:     {0}\nValue:    {1}\nHashCode: {2}\n",
				o.GetType().FullName, o.ToString(), o.GetHashCode());
		}
	}
}

// This program will display output similar to the following: 
// 
// Creating instance of: System.EventArgs 
// Creating instance of: System.Random 
// Creating instance of: System.Exception 
// Creating instance of: System.Object 
// Creating instance of: System.Version 
// 
// Objects and their default values: 
// 
// Type:     System.EventArgs 
// Value:    System.EventArgs 
// HashCode: 46104728 
// 
// Type:     System.Random 
// Value:    System.Random 
// HashCode: 12289376 
// 
// Type:     System.Exception 
// Value:    System.Exception: Exception of type 'System.Exception' was thrown. 
// HashCode: 55530882 
// 
// Type:     System.Object 
// Value:    System.Object 
// HashCode: 30015890 
// 
// Type:     System.Version 
// Value:    0.0 
// HashCode: 1048575

Solution 4 - C#

You can also do this -

var handle = Activator.CreateInstance("AssemblyName", 
                "Full name of the class including the namespace and class name");
var obj = handle.Unwrap();

Solution 5 - C#

A good example could be next: for instance you have a set of Loggers and you allows user to specify type to be used in runtime via configuration file.

Then:

string rawLoggerType = configurationService.GetLoggerType();
Type loggerType = Type.GetType(rawLoggerType);
ILogger logger = Activator.CreateInstance(loggerType.GetType()) as ILogger;

OR another case is when you have a common entities factory, which creates entity, and is also responsible on initialization of an entity by data received from DB:

(pseudocode)

public TEntity CreateEntityFromDataRow<TEntity>(DataRow row)
 where TEntity : IDbEntity, class
{
   MethodInfo methodInfo = typeof(T).GetMethod("BuildFromDataRow");
   TEntity instance = Activator.CreateInstance(typeof(TEntity)) as TEntity;
   return methodInfo.Invoke(instance, new object[] { row } ) as TEntity;
}

Solution 6 - C#

The Activator.CreateInstance method creates an instance of a specified type using the constructor that best matches the specified parameters.

For example, let's say that you have the type name as a string, and you want to use the string to create an instance of that type. You could use Activator.CreateInstance for this:

string objTypeName = "Foo";
Foo foo = (Foo)Activator.CreateInstance(Type.GetType(objTypeName));

Here's an MSDN article that explains it's application in more detail:

http://msdn.microsoft.com/en-us/library/wccyzw83.aspx

Solution 7 - C#

Building off of deepee1 and this, here's how to accept a class name in a string, and then use it to read and write to a database with LINQ. I use "dynamic" instead of deepee1's casting because it allows me to assign properties, which allows us to dynamically select and operate on any table we want.

Type tableType = Assembly.GetExecutingAssembly().GetType("NameSpace.TableName");
ITable itable = dbcontext.GetTable(tableType);

//prints contents of the table
foreach (object y in itable) {
    string value = (string)y.GetType().GetProperty("ColumnName").GetValue(y, null);
    Console.WriteLine(value);
}

//inserting into a table
dynamic tableClass = Activator.CreateInstance(tableType);
//Alternative to using tableType, using Tony's tips
dynamic tableClass = Activator.CreateInstance(null, "NameSpace.TableName").Unwrap();
tableClass.Word = userParameter;
itable.InsertOnSubmit(tableClass);
dbcontext.SubmitChanges();

//sql equivalent
dbcontext.ExecuteCommand("INSERT INTO [TableNme]([ColumnName]) VALUES ({0})", userParameter);

Solution 8 - C#

Why would you use it if you already knew the class and were going to cast it? Why not just do it the old fashioned way and make the class like you always make it? There's no advantage to this over the way it's done normally. Is there a way to take the text and operate on it thusly:

label1.txt = "Pizza" 
Magic(label1.txt) p = new Magic(lablel1.txt)(arg1, arg2, arg3);
p.method1();
p.method2();

If I already know its a Pizza there's no advantage to:

p = (Pizza)somefancyjunk("Pizza"); over
Pizza p = new Pizza();

but I see a huge advantage to the Magic method if it exists.

Solution 9 - C#

Coupled with reflection, I found Activator.CreateInstance to be very helpful in mapping stored procedure result to a custom class as described in the following answer.

Solution 10 - C#

We used it for something like e.g.

public interface IExample
{
    void DoSomethingAmazing();
}

public class ExampleA : IExample
{
    public void DoSomethingAmazing()
    {
        Console.WriteLine("AAAA");
    }

    public void DoA()
    {
        Console.WriteLine("A")
    }
}

public class ExampleB : IExample
{
    public void DoSomethingAmazing()
    {
        Console.WriteLine("BBBB");
    }

    public void DoB()
    {
        Console.WriteLine("B")
    }
}

and then provided the type serialized from a settings file

=> Even after compilation we can still change the applications behaviour by using different settings

Something like e.g.

public static class Programm
{
    public static void Main()
    {
        var type = MagicMethodThatReadsASerializedTypeFromTheSettings();
        var example = (IExample) Activator.CreateInstance(type);

        example.DoSomethingAmazing();

        switch(example)
        {
            case ExampleA a:
                a.DoA();
                break;

            case ExampleB b:
                b.DoB();
                break;
        }
    }
}

And I use it in a custom multi-user serialization where I send RPC (Remote Procedure Calls) to other devices with parameters.

Extremly cropped to the necesarry it basically does

public ISendable
{
    public byte[] ToBytes();
    public void FromBytes(byte[] bytes);
}

// Converts any ISendable into a byte[] with the content
// typeBytes + contentBytes
public byte[] ToBytes(ISendable toSend)
{
    var typeBytes = Encoding.ASCII.GetBytes(toSend.GetType().AssemblyQualifiedName);
    var contentBytes = ISendable.ToBytes();

    return MagicMethodToCombineByteArrays(typeBytes, contentBytes);
}

// Coonverts back from byte[] to the according ISendable
// by first reading the type, creating the instance and filling it with
// contentBytes
public T FromBytes<T>(byte[] bytes) where T : ISendable
{
    MagicMethodToSplitInputBytes(out var typeBytes, out var contentBytes);
    var type = Encoding.ASCII.GetString(typeBytes);

    var instance = (T) Activator.CreateInstance(type);
    instance.FromBytes(contentBytes);

    return instance;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTabriz AtayiView Question on Stackoverflow
Solution 1 - C#deepee1View Answer on Stackoverflow
Solution 2 - C#dowhileforView Answer on Stackoverflow
Solution 3 - C#Claus JørgensenView Answer on Stackoverflow
Solution 4 - C#WilliamView Answer on Stackoverflow
Solution 5 - C#sllView Answer on Stackoverflow
Solution 6 - C#James JohnsonView Answer on Stackoverflow
Solution 7 - C#DharmaTurtleView Answer on Stackoverflow
Solution 8 - C#user8659016View Answer on Stackoverflow
Solution 9 - C#usefulBeeView Answer on Stackoverflow
Solution 10 - C#derHugoView Answer on Stackoverflow