/src/LinFu.IoC/Configuration/Resolvers/ConstructorArgumentResolver.cs

http://github.com/philiplaureano/LinFu · C# · 87 lines · 44 code · 13 blank · 30 comment · 3 complexity · 80b87dea903b61188159f9cc0c269536 MD5 · raw file

  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using System.Reflection;
  4. using LinFu.IoC.Configuration.Interfaces;
  5. using LinFu.IoC.Interfaces;
  6. namespace LinFu.IoC.Configuration.Resolvers
  7. {
  8. /// <summary>
  9. /// Represents a class that determines the method arguments that should be used for a given constructor.
  10. /// </summary>
  11. public class ConstructorArgumentResolver : IConstructorArgumentResolver, IInitialize
  12. {
  13. private IArgumentResolver _argumentResolver;
  14. /// <summary>
  15. /// Determines the parameter values that should be used for a given constructor.
  16. /// </summary>
  17. /// <param name="constructor">The target constructor.</param>
  18. /// <param name="container">The host container instance.</param>
  19. /// <param name="additionalArguments">
  20. /// The list of additional arguments that should be combined with the arguments from the
  21. /// container.
  22. /// </param>
  23. /// <returns>A list of arguments that will be used for the given constructor.</returns>
  24. public object[] GetConstructorArguments(ConstructorInfo constructor, IServiceContainer container,
  25. object[] additionalArguments)
  26. {
  27. var parameterTypes = GetMissingParameterTypes(constructor, additionalArguments);
  28. // Generate the arguments for the target constructor
  29. return _argumentResolver.ResolveFrom(parameterTypes, container,
  30. additionalArguments);
  31. }
  32. /// <summary>
  33. /// Initializes the class with the default services.
  34. /// </summary>
  35. /// <param name="container">The target service container.</param>
  36. public void Initialize(IServiceContainer container)
  37. {
  38. _argumentResolver = container.GetService<IArgumentResolver>();
  39. }
  40. /// <summary>
  41. /// Determines which parameter types need to be supplied to invoke a particular
  42. /// <paramref name="constructor" /> instance.
  43. /// </summary>
  44. /// <param name="constructor">The target constructor.</param>
  45. /// <param name="additionalArguments">The additional arguments that will be used to invoke the constructor.</param>
  46. /// <returns>The list of parameter types that are still missing parameter values.</returns>
  47. private static IEnumerable<INamedType> GetMissingParameterTypes(ConstructorInfo constructor,
  48. IEnumerable<object> additionalArguments)
  49. {
  50. var parameters = from p in constructor.GetParameters()
  51. select p;
  52. // Determine which parameters need to
  53. // be supplied by the container
  54. var parameterTypes = new List<INamedType>();
  55. var argumentCount = additionalArguments.Count();
  56. if (additionalArguments != null && argumentCount > 0)
  57. {
  58. // Supply parameter values for the
  59. // parameters that weren't supplied by the
  60. // additionalArguments
  61. var parameterCount = parameters.Count();
  62. var maxIndex = parameterCount - argumentCount;
  63. var targetParameters = from param in parameters.Where(p => p.Position < maxIndex)
  64. select new NamedType(param) as INamedType;
  65. parameterTypes.AddRange(targetParameters);
  66. return parameterTypes;
  67. }
  68. var results = from param in parameters
  69. select new NamedType(param) as INamedType;
  70. parameterTypes.AddRange(results);
  71. return parameterTypes;
  72. }
  73. }
  74. }