/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
- using System;
- using System.Collections.Generic;
- using LinFu.IoC.Interfaces;
- using LinFu.Reflection;
- namespace LinFu.IoC.Configuration
- {
- /// <summary>
- /// A class that initializes service instances that use
- /// the <see cref="IInitialize{T}" /> interface.
- /// </summary>
- public class Initializer<T> : IPostProcessor
- {
- private static readonly HashSet<HashableWeakReference> _instances =
- new HashSet<HashableWeakReference>(new HashableWeakReferenceComparer());
- private static int _initializeCallCount;
- private readonly Func<IServiceRequestResult, T> _getSource;
- /// <summary>
- /// Initializes the class with the given <paramref name="getSource" /> delegate.
- /// </summary>
- /// <param name="getSource">
- /// The functor that will obtain the object instance that will be used to initialize a given
- /// service.
- /// </param>
- public Initializer(Func<IServiceRequestResult, T> getSource)
- {
- _getSource = getSource;
- }
- /// <summary>
- /// Initializes every service that implements
- /// the <see cref="IInitialize{T}" /> interface.
- /// </summary>
- /// <param name="result">
- /// The <see cref="IServiceRequestResult" /> instance that contains the service instance to be
- /// initialized.
- /// </param>
- public void PostProcess(IServiceRequestResult result)
- {
- var originalResult = result.OriginalResult as IInitialize<T>;
- var actualResult = result.ActualResult as IInitialize<T>;
- var source = _getSource(result);
- // Initialize the original result, if possible
- Initialize(originalResult, source);
- // Initialize the actual result
- Initialize(actualResult, source);
- }
- /// <summary>
- /// Initializes the <paramref name="target" /> with the given <paramref name="source" /> instance.
- /// </summary>
- /// <param name="target">The target to initialize.</param>
- /// <param name="source">The instance that will be introduced to the <see cref="IInitialize{T}" /> instance.</param>
- private static void Initialize(IInitialize<T> target, T source)
- {
- if (target == null)
- return;
- if ((_initializeCallCount = ++_initializeCallCount % 100) == 0)
- _instances.RemoveWhere(w => w != null && !w.IsAlive);
- // Make sure that the target is initialized only once
- var weakReference = new HashableWeakReference(target);
- if (_instances.Contains(weakReference))
- return;
- // Initialize the target
- target.Initialize(source);
- _instances.Add(weakReference);
- }
- private class HashableWeakReference : WeakReference
- {
- private readonly int _hashCode;
- public HashableWeakReference(object target)
- : base(target, false)
- {
- _hashCode = target.GetHashCode();
- }
- public override int GetHashCode()
- {
- return _hashCode;
- }
- }
- private class HashableWeakReferenceComparer : IEqualityComparer<HashableWeakReference>
- {
- public bool Equals(HashableWeakReference x, HashableWeakReference y)
- {
- if (x == null || y == null)
- return false;
- return x.Target == y.Target;
- }
- int IEqualityComparer<HashableWeakReference>.GetHashCode(HashableWeakReference obj)
- {
- if (obj == null) throw new ArgumentNullException("obj");
- return obj.GetHashCode();
- }
- }
- }
- }