Improve DI system

This commit is contained in:
Finite Reality
2016-07-21 00:23:49 +01:00
parent e266fa8b32
commit f7455c389b
5 changed files with 40 additions and 28 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@@ -6,33 +7,39 @@ namespace Discord.Commands
{
internal class ReflectionUtils
{
internal static object CreateObject(TypeInfo typeInfo, CommandService commands, IDependencyMap map = null)
internal static object CreateObject(TypeInfo typeInfo, CommandService service, IDependencyMap map = null)
{
if (typeInfo.DeclaredConstructors.Count() > 1)
throw new InvalidOperationException($"Found too many constructors for \"{typeInfo.FullName}\"");
var constructor = typeInfo.DeclaredConstructors.FirstOrDefault();
if (constructor == null)
throw new InvalidOperationException($"Found no constructor for \"{typeInfo.FullName}\"");
object[] parameters;
try
{
if (constructor.GetParameters().Length == 0)
return constructor.Invoke(null);
else if (constructor.GetParameters().Length > 1)
throw new InvalidOperationException($"Could not find a valid constructor for \"{typeInfo.FullName}\" (Found too many parameters)");
var parameter = constructor.GetParameters().FirstOrDefault();
if (parameter == null)
throw new InvalidOperationException($"Could not find a valid constructor for \"{typeInfo.FullName}\" (No valid parameters)");
if (parameter.ParameterType == typeof(CommandService))
return constructor.Invoke(new object[1] { commands });
else if (parameter.ParameterType == typeof(IDependencyMap))
{
if (map == null) throw new InvalidOperationException($"The constructor for \"{typeInfo.FullName}\" requires a Dependency Map.");
return constructor.Invoke(new object[1] { map });
}
else
throw new InvalidOperationException($"Could not find a valid constructor for \"{typeInfo.FullName}\" (Invalid Parameter Type: \"{parameter.ParameterType.FullName}\")");
// TODO: probably change this ternary into something sensible
parameters = constructor.GetParameters()
.Select(x => x.ParameterType == typeof(CommandService) ? service : map.Get(x.ParameterType)).ToArray();
}
catch (Exception e)
catch (KeyNotFoundException ex) // tried to inject an invalid dependency
{
throw new InvalidOperationException($"Could not find a valid constructor for \"{typeInfo.FullName}\" (Error invoking constructor)");
throw new InvalidOperationException($"Could not find a valid constructor for \"{typeInfo.FullName}\" (could not provide parameter)", ex);
}
catch (NullReferenceException ex) // tried to find a dependency
{
throw new InvalidOperationException($"Could not find a valid constructor for \"{typeInfo.FullName}\" (type requires dependency injection)", ex);
}
try
{
return constructor.Invoke(parameters);
}
catch (Exception ex)
{
throw new InvalidOperationException($"Could not find a valid constructor for \"{typeInfo.FullName}\" (Error invoking constructor)", ex);
}
}
}