Add FindType method to ObjectCreator

This commit is contained in:
ScottNZ
2013-11-15 21:56:23 +13:00
parent 0a50371a37
commit b2f46a56ea

View File

@@ -19,13 +19,15 @@ namespace OpenRA
{ {
public class ObjectCreator public class ObjectCreator
{ {
Pair<Assembly, string>[] modAssemblies; Pair<Assembly, string>[] assemblies;
public ObjectCreator(Manifest manifest) public ObjectCreator(Manifest manifest)
{ {
// All the core namespaces // All the core namespaces
var asms = typeof(Game).Assembly.GetNamespaces() var asms = typeof(Game).Assembly.GetNamespaces() // Game
.Select(c => Pair.New(typeof(Game).Assembly, c)) .Select(c => Pair.New(typeof(Game).Assembly, c))
.Concat(typeof(Mod).Assembly.GetNamespaces() // FileFormats
.Select(c => Pair.New(typeof(Mod).Assembly, c)))
.ToList(); .ToList();
// Namespaces from each mod assembly // Namespaces from each mod assembly
@@ -35,7 +37,7 @@ namespace OpenRA
asms.AddRange(asm.GetNamespaces().Select(ns => Pair.New(asm, ns))); asms.AddRange(asm.GetNamespaces().Select(ns => Pair.New(asm, ns)));
} }
modAssemblies = asms.ToArray(); assemblies = asms.ToArray();
} }
public static Action<string> MissingTypeAction = public static Action<string> MissingTypeAction =
@@ -48,24 +50,30 @@ namespace OpenRA
public T CreateObject<T>(string className, Dictionary<string, object> args) public T CreateObject<T>(string className, Dictionary<string, object> args)
{ {
foreach (var mod in modAssemblies) var type = FindType(className);
if (type == null)
{ {
var type = mod.First.GetType(mod.Second + "." + className, false); MissingTypeAction(className);
if (type == null) continue; return default(T);
var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
var ctors = type.GetConstructors(flags)
.Where(x => x.HasAttribute<UseCtorAttribute>()).ToList();
if (ctors.Count == 0)
return (T)CreateBasic(type);
else if (ctors.Count == 1)
return (T)CreateUsingArgs(ctors[0], args);
else
throw new InvalidOperationException("ObjectCreator: UseCtor on multiple constructors; invalid.");
} }
MissingTypeAction(className); var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
return default(T); var ctors = type.GetConstructors(flags)
.Where(x => x.HasAttribute<UseCtorAttribute>()).ToList();
if (ctors.Count == 0)
return (T)CreateBasic(type);
else if (ctors.Count == 1)
return (T)CreateUsingArgs(ctors[0], args);
else
throw new InvalidOperationException("ObjectCreator: UseCtor on multiple constructors; invalid.");
}
public Type FindType(string className)
{
return assemblies
.Select(pair => pair.First.GetType(pair.Second + "." + className, false))
.FirstOrDefault(t => t != null);
} }
public object CreateBasic(Type type) public object CreateBasic(Type type)
@@ -90,7 +98,7 @@ namespace OpenRA
public IEnumerable<Type> GetTypesImplementing<T>() public IEnumerable<Type> GetTypesImplementing<T>()
{ {
var it = typeof(T); var it = typeof(T);
return modAssemblies.Select(ma => ma.First).Distinct() return assemblies.Select(ma => ma.First).Distinct()
.SelectMany(ma => ma.GetTypes() .SelectMany(ma => ma.GetTypes()
.Where(t => t != it && it.IsAssignableFrom(t))); .Where(t => t != it && it.IsAssignableFrom(t)));
} }