[.net] Activator.CreateInstance as T

Started by
4 comments, last by iliak 14 years, 8 months ago
Hi I'm scripting the monster in my game. Here's the interface for each monsters :

/// <summary>
/// Interface for monsters
/// </summary>
public interface IMonster
{
	void OnUpdate();

	void OnDraw();
}

An example for the RustMonster type. This source is loaded at runtime as a plain text (.cs) file and compiled on the fly. So I dont know it at compile time (the goal of scripting monsters...).

public class RustMonster : IMonster
{
	public void OnUpdate()
	{
		Trace.WriteLine("OnUpdate()");
	}

	public void OnDraw()
	{
		Trace.WriteLine("OnDraw()");
	}
}

I would like to create a new instance of RustMonster like this

	// Somewhere in my code
	IMonster rust = Script.CreateInstance<IMonster>("RustMonster");

CreateInstace definition

	public class Script
	{
		/// <summary>
		/// Creates an instance of T
		/// </summary>
		/// <typeparam name="T">Type of the instance</typeparam>
		/// <param name="name">Name of the class</param>
		/// <returns>An instance of or default(T)</returns>
		public T CreateInstance<T>(string name)
		{
			if (!IsCompiled)
			{
				Trace.WriteLine("Script \"" + Name + "\" is not compiled. Can't create a new instance \"" + name + "\" of type \"" + typeof(T).Name + "\"");
				return default(T);
			}

			// Get type
			Type t = CompiledAssembly.GetType(name, false);


			// Check interface
			if (t.GetInterface(typeof(T).Name) == null)
			{
				Trace.WriteLine("Type \"" + Name + "\" found, but not an instance of \"" + typeof(T).Name + "\".");
				return default(T);
			}

			// Create an instance
			var ret = Activator.CreateInstance(t);		// <--- Here is the problem
			return ret;
		}
	}

How can I "cast" the return as T ?
- Iliak -
[ ArcEngine: An open source .Net gaming framework ]
[ Dungeon Eye: An open source remake of Eye of the Beholder II ]
Advertisement
You can do an explicit cast (T), or use the as operator if you constrain your generic parameter to class.
Mike Popoloski | Journal | SlimDX
Constrain will do the job, thank you !

		public T CreateInstance<T>(string name) where T : class		{			if (!IsCompiled)			{				Trace.WriteLine("Script \"" + Name + "\" is not compiled. Can't create a new instance \"" + name + "\" of type \"" + typeof(T).Name + "\"");				return default(T);			}			// Get type			Type t = CompiledAssembly.GetType(name, false);			if (t == null)			{				Trace.WriteLine("Type \"" + Name + "\" found, but not an instance of \"" + typeof(T).Name + "\".");				return default(T);			}			// Check interface			if (t.GetInterface(typeof(T).Name) == null)			{				Trace.WriteLine("Type \"" + Name + "\" found, but not an instance of \"" + typeof(T).Name + "\".");				return default(T);			}			// Create an instance			return Activator.CreateInstance(t) as T;		}
- Iliak -
[ ArcEngine: An open source .Net gaming framework ]
[ Dungeon Eye: An open source remake of Eye of the Beholder II ]
Just remember that "as T" won't throw an exception like it would if you just cast using "(T)" - instead, if the cast is invalid, it will just return null. Make sure this makes sense for your code.
NetGore - Open source multiplayer RPG engine
By the way, you might want to replace

if (t.GetInterface(typeof(T).Name) == null)

with
if (!typeof(T).IsAssignableFrom(t))


This is a safer way (not string based) to check whether t implements/derives from T.
Andre Loker | Personal blog on .NET
Yes it's safer, thank you.
- Iliak -
[ ArcEngine: An open source .Net gaming framework ]
[ Dungeon Eye: An open source remake of Eye of the Beholder II ]

This topic is closed to new replies.

Advertisement