/src/LinFu.Reflection/AssemblyActionLoader.cs

http://github.com/philiplaureano/LinFu · C# · 133 lines · 58 code · 14 blank · 61 comment · 12 complexity · 497215cdc4f1399657a30bd4f2b8bb4f MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. namespace LinFu.Reflection
  6. {
  7. /// <summary>
  8. /// A class that reads an assembly and converts it into a set of actions
  9. /// that can be used to build the list of actions against the <typeparamref name="TTarget" />
  10. /// type.
  11. /// </summary>
  12. /// <typeparam name="TTarget">The target type.</typeparam>
  13. /// <typeparam name="TAssembly">The assembly type.</typeparam>
  14. /// <typeparam name="TType">The target input type.</typeparam>
  15. public class AssemblyActionLoader<TTarget, TAssembly, TType> : IActionLoader<IList<Action<TTarget>>, TAssembly>
  16. {
  17. private readonly Func<IList<IActionLoader<TTarget, TType>>> _getTypeLoaders;
  18. /// <summary>
  19. /// Initializes the class with a set of <see cref="IActionLoader{TTarget,Type}" />
  20. /// instances that will be used to load the target assembly.
  21. /// </summary>
  22. /// <param name="getTypeLoaders">The delegate that will return the actual list of typeloaders.</param>
  23. /// <param name="typeExtractor">
  24. /// The type extractor that will be responsible for pulling the types out of the current
  25. /// assembly.
  26. /// </param>
  27. public AssemblyActionLoader(Func<IList<IActionLoader<TTarget, TType>>> getTypeLoaders,
  28. ITypeExtractor<TAssembly, TType> typeExtractor)
  29. {
  30. _getTypeLoaders = getTypeLoaders;
  31. TypeExtractor = typeExtractor;
  32. }
  33. /// <summary>
  34. /// The <see cref="ITypeExtractor" /> instance that will
  35. /// determine which types will be extracted from an assembly.
  36. /// </summary>
  37. public ITypeExtractor<TAssembly, TType> TypeExtractor { get; set; }
  38. /// <summary>
  39. /// Loads the target assembly and creates an action that can
  40. /// create the list of actions which will modify the <typeparamref name="TTarget" /> instance.
  41. /// </summary>
  42. /// <param name="input">The target assembly.</param>
  43. /// <returns>
  44. /// The list of actions which will modify the list of actions that will be executed against the
  45. /// <typeparamref name="TTarget" /> instance.
  46. /// </returns>
  47. public IEnumerable<Action<IList<Action<TTarget>>>> Load(TAssembly input)
  48. {
  49. yield return list => CreateActionsFrom(input, list);
  50. }
  51. /// <summary>
  52. /// Determines if an assembly can be loaded.
  53. /// </summary>
  54. /// <param name="assembly">The target assembly.</param>
  55. /// <returns>Returns <c>true</c> if the assembly is not <c>null</c>.</returns>
  56. public virtual bool CanLoad(TAssembly assembly)
  57. {
  58. return assembly != null;
  59. }
  60. /// <summary>
  61. /// Generates a list of actions from a target assemby.
  62. /// </summary>
  63. /// <param name="assembly">The target assembly.</param>
  64. /// <param name="resultList">The list that will store the resulting actions.</param>
  65. private void CreateActionsFrom(TAssembly assembly, ICollection<Action<TTarget>> resultList)
  66. {
  67. // Grab the types embedded in the assembly
  68. IEnumerable<TType> types = new TType[0];
  69. if (assembly != null && TypeExtractor != null)
  70. types = TypeExtractor.GetTypes(assembly);
  71. // Pass the loaded types to
  72. // the type loaders for processing
  73. foreach (var type in types)
  74. {
  75. // Skip any invalid types
  76. if (type == null)
  77. continue;
  78. LoadResultsFromType(type, resultList);
  79. }
  80. }
  81. /// <summary>
  82. /// Generates the list of <see cref="Action{TTarget}" />
  83. /// instances which will be used to configure a target instance.
  84. /// </summary>
  85. /// <param name="type">The <see cref="Type" /> instance that holds the configuration information.</param>
  86. /// <param name="results">The list that will hold the actions which will configure the container.</param>
  87. private void LoadResultsFromType(TType type, ICollection<Action<TTarget>> results)
  88. {
  89. var typeLoaders = _getTypeLoaders();
  90. foreach (var typeLoader in typeLoaders)
  91. {
  92. if (typeLoader == null || !typeLoader.CanLoad(type))
  93. continue;
  94. var actions = typeLoader.Load(type);
  95. if (actions.Count() == 0)
  96. continue;
  97. foreach (var action in actions) results.Add(action);
  98. }
  99. }
  100. }
  101. /// <summary>
  102. /// A class that reads an assembly and converts it into a set of actions
  103. /// that can be used to build the list of actions against the <typeparamref name="TTarget" />
  104. /// type.
  105. /// </summary>
  106. /// <typeparam name="TTarget">The target type.</typeparam>
  107. public class AssemblyActionLoader<TTarget> : AssemblyActionLoader<TTarget, Assembly, Type>
  108. {
  109. /// <summary>
  110. /// Initializes the class with a set of <see cref="IActionLoader{TTarget,Type}" />
  111. /// instances that will be used to load the target assembly.
  112. /// </summary>
  113. /// <param name="getTypeLoaders">The delegate that will return the actual list of typeloaders.</param>
  114. public AssemblyActionLoader(Func<IList<IActionLoader<TTarget, Type>>> getTypeLoaders)
  115. : base(getTypeLoaders, new TypeExtractor())
  116. {
  117. }
  118. }
  119. }