using System; using System.Collections.Generic; using LibGit2Sharp.Core.Compat; namespace LibGit2Sharp.Core { internal abstract class LazyGroup { private readonly IList> evaluators = new List>(); private readonly object @lock = new object(); private bool evaluated; protected readonly Repository repo; protected LazyGroup(Repository repo) { this.repo = repo; } public ILazy AddLazy(Func func) { var prop = new Dependent(func, this); evaluators.Add(prop); return prop; } public void Evaluate() { if (evaluated) return; lock (@lock) { if (evaluated) return; EvaluateInternal(input => { foreach (var e in evaluators) e.Evaluate(input); }); evaluated = true; } } protected abstract void EvaluateInternal(Action evaluator); protected static ILazy Singleton(Func resultSelector) { return new LazyWrapper(resultSelector); } private interface IEvaluator { void Evaluate(TInput input); } private class Dependent : ILazy, IEvaluator { private readonly Func valueFactory; private readonly LazyGroup lazyGroup; private TOutput value; private bool hasBeenEvaluated; public Dependent(Func valueFactory, LazyGroup lazyGroup) { this.valueFactory = valueFactory; this.lazyGroup = lazyGroup; } public TOutput Value { get { return Evaluate(); } } private TOutput Evaluate() { if (!hasBeenEvaluated) { lazyGroup.Evaluate(); } return value; } void IEvaluator.Evaluate(TInput input) { value = valueFactory(input); hasBeenEvaluated = true; } } protected class LazyWrapper : Lazy, ILazy { public LazyWrapper(Func evaluator) : base(evaluator) { } } } }