Sign in to follow this  
iliak

[.net] Activator.CreateInstance as T

Recommended Posts

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 ?

Share this post


Link to post
Share on other sites
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;
}

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this