You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

ReflectionUtils.cs 3.0 kB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. namespace Discord.Commands
  6. {
  7. internal class ReflectionUtils
  8. {
  9. internal static object CreateObject(TypeInfo typeInfo, CommandService service, IDependencyMap map = null)
  10. {
  11. if (typeInfo.DeclaredConstructors.Count() > 1)
  12. throw new InvalidOperationException($"Found too many constructors for \"{typeInfo.FullName}\"");
  13. var constructor = typeInfo.DeclaredConstructors.FirstOrDefault();
  14. if (constructor == null)
  15. throw new InvalidOperationException($"Found no constructor for \"{typeInfo.FullName}\"");
  16. object[] arguments = null;
  17. ParameterInfo[] parameters = constructor.GetParameters();
  18. // TODO: can this logic be made better/cleaner?
  19. if (parameters.Length == 1)
  20. {
  21. if (parameters[0].ParameterType == typeof(IDependencyMap))
  22. {
  23. if (map != null)
  24. arguments = new object[] { map };
  25. else
  26. throw new InvalidOperationException($"Could not find a valid constructor for \"{typeInfo.FullName}\" (an IDependencyMap is required)");
  27. }
  28. }
  29. else if (parameters.Length == 2)
  30. {
  31. if (parameters[0].ParameterType == typeof(CommandService) && parameters[1].ParameterType == typeof(IDependencyMap))
  32. if (map != null)
  33. arguments = new object[] { service, map };
  34. else
  35. throw new InvalidOperationException($"Could not find a valid constructor for \"{typeInfo.FullName}\" (an IDependencyMap is required)");
  36. }
  37. if (arguments == null)
  38. {
  39. try
  40. {
  41. // TODO: probably change this ternary into something sensible?
  42. arguments = parameters.Select(x => x.ParameterType == typeof(CommandService) ? service : map.Get(x.ParameterType)).ToArray();
  43. }
  44. catch (KeyNotFoundException ex) // tried to inject an invalid dependency
  45. {
  46. throw new InvalidOperationException($"Could not find a valid constructor for \"{typeInfo.FullName}\" (could not provide parameter)", ex);
  47. }
  48. catch (NullReferenceException ex) // tried to find a dependency
  49. {
  50. throw new InvalidOperationException($"Could not find a valid constructor for \"{typeInfo.FullName}\" (an IDependencyMap is required)", ex);
  51. }
  52. }
  53. try
  54. {
  55. return constructor.Invoke(arguments);
  56. }
  57. catch (Exception ex)
  58. {
  59. throw new InvalidOperationException($"Could not create \"{typeInfo.FullName}\"", ex);
  60. }
  61. }
  62. }
  63. }