/Core/Containers/TypeContainer.cs

https://github.com/mehfuzh/AutoBox
C# | 134 lines | 93 code | 22 blank | 19 comment | 15 complexity | 9ed9d70a083a973b4d3396babb94eb9f MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using AutoBox.Abstraction;
  6. namespace AutoBox.Containers
  7. {
  8. /// <summary>
  9. /// Register and maps the target type.
  10. /// </summary>
  11. public class TypeContainer : IContainer
  12. {
  13. /// <summary>
  14. /// Initialize the instance of <see cref="TypeContainer"/> class.
  15. /// </summary>
  16. public TypeContainer(Assembly assembly, IContainer container)
  17. {
  18. this.assembly = assembly;
  19. this.container = container;
  20. }
  21. /// <summary>
  22. /// Registers an interface to its corresponding type.
  23. /// </summary>
  24. public void Register(Type @interface, Type targetType)
  25. {
  26. RegisterDependencies(targetType);
  27. container.Register(@interface, targetType);
  28. }
  29. /// <summary>
  30. /// Registers an interface to its corresponding type.
  31. /// </summary>
  32. /// <typeparam name="T">Target type</typeparam>
  33. public T Resolve<T>()
  34. {
  35. return (T)Resolve(typeof(T));
  36. }
  37. /// <summary>
  38. /// Resolve the target type with necessary dependencies.
  39. /// </summary>
  40. public object Resolve(Type serviceType)
  41. {
  42. ResigerServiceAsNecessary(serviceType);
  43. var instance = container.Resolve(serviceType);
  44. if (instance != null)
  45. return instance;
  46. object result = ResolveOnDemand(serviceType);
  47. if (result == null)
  48. throw new ArgumentException(string.Format(Messages.NoSuitableCtorToResolve, serviceType.Name));
  49. return result;
  50. }
  51. /// <summary>
  52. /// Resolves all registered instances for a specific service type.
  53. /// </summary>
  54. public IList<object> ResolveAll(Type serviceType)
  55. {
  56. ResigerServiceAsNecessary(serviceType);
  57. return container.ResolveAll(serviceType);
  58. }
  59. private void ResigerServiceAsNecessary(Type serviceType)
  60. {
  61. if (serviceType.IsNewService(container)) RegisterService(serviceType);
  62. }
  63. private void RegisterService(Type serviceType)
  64. {
  65. IEnumerable<Type> resolvedTypes = assembly.GetTypes().Where(x => x.GetInterfaces().Any(t => t == serviceType));
  66. if (resolvedTypes.Count() == 0)
  67. {
  68. throw new AutoBoxException(string.Format(Messages.FailedToResolveCorrespondingType, serviceType.Name));
  69. }
  70. foreach (var resolvedType in resolvedTypes)
  71. {
  72. if (resolvedType != null && serviceType.IsAssignableFrom(resolvedType))
  73. {
  74. Register(serviceType, resolvedType);
  75. }
  76. }
  77. }
  78. private void RegisterDependencies(Type resolvedType)
  79. {
  80. foreach (var constructor in resolvedType.GetConstructors())
  81. {
  82. var parameterInfos = constructor.GetParameters();
  83. foreach (var parameterInfo in parameterInfos)
  84. {
  85. if (parameterInfo.ParameterType.IsNewService(container))
  86. {
  87. RegisterService(parameterInfo.ParameterType);
  88. }
  89. }
  90. }
  91. }
  92. private object ResolveOnDemand(Type targetType)
  93. {
  94. foreach (var constructor in targetType.GetConstructors())
  95. {
  96. var parameters = constructor.GetParameters();
  97. object[] args = new object[parameters.Length];
  98. for (int index = 0; index < parameters.Length; index++)
  99. {
  100. var value = Resolve(parameters[index].ParameterType);
  101. if (value == null)
  102. continue;
  103. args[index] = value;
  104. }
  105. return constructor.Invoke(args);
  106. }
  107. return null;
  108. }
  109. private readonly Assembly assembly;
  110. private readonly IContainer container;
  111. }
  112. }