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

http://github.com/philiplaureano/LinFu · C# · 98 lines · 44 code · 13 blank · 41 comment · 5 complexity · 9ec6cfae756d6ba122d1c293d7f8d0a3 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Reflection;
  5. using LinFu.IoC.Configuration.Interfaces;
  6. using LinFu.IoC.Interfaces;
  7. namespace LinFu.IoC.Configuration
  8. {
  9. /// <summary>
  10. /// Represents a class that can choose a member that best matches
  11. /// the services currently available in a given <see cref="IServiceContainer" /> instance.
  12. /// </summary>
  13. /// <typeparam name="TMember">The member type that will be searched.</typeparam>
  14. public abstract class MemberResolver<TMember> : IMemberResolver<TMember>
  15. where TMember : MethodBase
  16. {
  17. private readonly Func<IServiceContainer, IMethodFinder<TMember>> _getFinder;
  18. /// <summary>
  19. /// The default constructor for the <see cref="MemberResolver{TMember}" /> class.
  20. /// </summary>
  21. protected MemberResolver()
  22. {
  23. _getFinder = container => container.GetService<IMethodFinder<TMember>>();
  24. }
  25. /// <summary>
  26. /// Initializes the class with a <paramref name="getFinder">functor</paramref>
  27. /// that will be used to instantiate the method finder that will be used in the search.
  28. /// </summary>
  29. /// <param name="getFinder">The functor that will be used to instantiate the method finder.</param>
  30. protected MemberResolver(Func<IServiceContainer, IMethodFinder<TMember>> getFinder)
  31. {
  32. _getFinder = getFinder;
  33. }
  34. /// <summary>
  35. /// Uses the <paramref name="container" /> to determine which member to use from
  36. /// the <paramref name="concreteType">concrete type</paramref>.
  37. /// </summary>
  38. /// <param name="concreteType">The target type.</param>
  39. /// <param name="container">The container that contains the member values that will be used to invoke the members.</param>
  40. /// <param name="finderContext">The <see cref="IMethodFinderContext" /> that describes the target method.</param>
  41. /// <returns>A member instance if a match is found; otherwise, it will return <c>null</c>.</returns>
  42. public TMember ResolveFrom(Type concreteType, IServiceContainer container,
  43. IMethodFinderContext finderContext)
  44. {
  45. var constructors = GetMembers(concreteType);
  46. if (constructors == null)
  47. return null;
  48. var resolver = GetMethodFinder(container);
  49. var bestMatch = resolver.GetBestMatch(constructors, finderContext);
  50. // If all else fails, find the
  51. // default constructor and use it as the
  52. // best match by default
  53. if (bestMatch == null)
  54. {
  55. var defaultResult = GetDefaultResult(concreteType);
  56. bestMatch = defaultResult;
  57. }
  58. Debug.Assert(bestMatch != null);
  59. return bestMatch;
  60. }
  61. /// <summary>
  62. /// Determines the <see cref="IMethodFinder{T}" /> that will be used
  63. /// in the method search.
  64. /// </summary>
  65. /// <param name="container"></param>
  66. /// <returns></returns>
  67. protected virtual IMethodFinder<TMember> GetMethodFinder(IServiceContainer container)
  68. {
  69. return _getFinder(container);
  70. }
  71. /// <summary>
  72. /// The method used to retrieve the default result if no
  73. /// other alternative is found.
  74. /// </summary>
  75. /// <param name="concreteType">The target type that contains the default member.</param>
  76. /// <returns>The default member result.</returns>
  77. protected abstract TMember GetDefaultResult(Type concreteType);
  78. /// <summary>
  79. /// Lists the members associated with the <paramref name="concreteType" />.
  80. /// </summary>
  81. /// <param name="concreteType">The target type that contains the type members.</param>
  82. /// <returns>A list of members that belong to the concrete type.</returns>
  83. protected abstract IEnumerable<TMember> GetMembers(Type concreteType);
  84. }
  85. }