/src/LinFu.IoC/Configuration/InitializerOfT.cs

http://github.com/philiplaureano/LinFu · C# · 114 lines · 65 code · 21 blank · 28 comment · 14 complexity · 9cbdc14f75655f20ba354f99d072a16c MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using LinFu.IoC.Interfaces;
  4. using LinFu.Reflection;
  5. namespace LinFu.IoC.Configuration
  6. {
  7. /// <summary>
  8. /// A class that initializes service instances that use
  9. /// the <see cref="IInitialize{T}" /> interface.
  10. /// </summary>
  11. public class Initializer<T> : IPostProcessor
  12. {
  13. private static readonly HashSet<HashableWeakReference> _instances =
  14. new HashSet<HashableWeakReference>(new HashableWeakReferenceComparer());
  15. private static int _initializeCallCount;
  16. private readonly Func<IServiceRequestResult, T> _getSource;
  17. /// <summary>
  18. /// Initializes the class with the given <paramref name="getSource" /> delegate.
  19. /// </summary>
  20. /// <param name="getSource">
  21. /// The functor that will obtain the object instance that will be used to initialize a given
  22. /// service.
  23. /// </param>
  24. public Initializer(Func<IServiceRequestResult, T> getSource)
  25. {
  26. _getSource = getSource;
  27. }
  28. /// <summary>
  29. /// Initializes every service that implements
  30. /// the <see cref="IInitialize{T}" /> interface.
  31. /// </summary>
  32. /// <param name="result">
  33. /// The <see cref="IServiceRequestResult" /> instance that contains the service instance to be
  34. /// initialized.
  35. /// </param>
  36. public void PostProcess(IServiceRequestResult result)
  37. {
  38. var originalResult = result.OriginalResult as IInitialize<T>;
  39. var actualResult = result.ActualResult as IInitialize<T>;
  40. var source = _getSource(result);
  41. // Initialize the original result, if possible
  42. Initialize(originalResult, source);
  43. // Initialize the actual result
  44. Initialize(actualResult, source);
  45. }
  46. /// <summary>
  47. /// Initializes the <paramref name="target" /> with the given <paramref name="source" /> instance.
  48. /// </summary>
  49. /// <param name="target">The target to initialize.</param>
  50. /// <param name="source">The instance that will be introduced to the <see cref="IInitialize{T}" /> instance.</param>
  51. private static void Initialize(IInitialize<T> target, T source)
  52. {
  53. if (target == null)
  54. return;
  55. if ((_initializeCallCount = ++_initializeCallCount % 100) == 0)
  56. _instances.RemoveWhere(w => w != null && !w.IsAlive);
  57. // Make sure that the target is initialized only once
  58. var weakReference = new HashableWeakReference(target);
  59. if (_instances.Contains(weakReference))
  60. return;
  61. // Initialize the target
  62. target.Initialize(source);
  63. _instances.Add(weakReference);
  64. }
  65. private class HashableWeakReference : WeakReference
  66. {
  67. private readonly int _hashCode;
  68. public HashableWeakReference(object target)
  69. : base(target, false)
  70. {
  71. _hashCode = target.GetHashCode();
  72. }
  73. public override int GetHashCode()
  74. {
  75. return _hashCode;
  76. }
  77. }
  78. private class HashableWeakReferenceComparer : IEqualityComparer<HashableWeakReference>
  79. {
  80. public bool Equals(HashableWeakReference x, HashableWeakReference y)
  81. {
  82. if (x == null || y == null)
  83. return false;
  84. return x.Target == y.Target;
  85. }
  86. int IEqualityComparer<HashableWeakReference>.GetHashCode(HashableWeakReference obj)
  87. {
  88. if (obj == null) throw new ArgumentNullException("obj");
  89. return obj.GetHashCode();
  90. }
  91. }
  92. }
  93. }