using System; namespace Marr.Data { public interface ILazyLoaded : ICloneable { bool IsLoaded { get; } void Prepare(Func dataMapperFactory, object parent); void LazyLoad(); } /// /// Allows a field to be lazy loaded. /// /// public class LazyLoaded : ILazyLoaded { protected TChild _value; public LazyLoaded() { } public LazyLoaded(TChild val) { _value = val; IsLoaded = true; } public TChild Value { get { LazyLoad(); return _value; } } public bool ShouldSerializeValue() { return IsLoaded; } public bool IsLoaded { get; protected set; } public virtual void Prepare(Func dataMapperFactory, object parent) { } public virtual void LazyLoad() { } public static implicit operator LazyLoaded(TChild val) { return new LazyLoaded(val); } public static implicit operator TChild(LazyLoaded lazy) { return lazy.Value; } public object Clone() { return MemberwiseClone(); } } /// /// This is the lazy loading proxy. /// /// The parent entity that contains the lazy loaded entity. /// The child entity that is being lazy loaded. internal class LazyLoaded : LazyLoaded { private TParent _parent; private Func _dbMapperFactory; private readonly Func _query; private readonly Func _condition; internal LazyLoaded(Func query, Func condition = null) { _query = query; _condition = condition; } public LazyLoaded(TChild val) : base(val) { _value = val; IsLoaded = true; } /// /// The second part of the initialization happens when the entity is being built. /// /// Knows how to instantiate a new IDataMapper. /// The parent entity. public override void Prepare(Func dataMapperFactory, object parent) { _dbMapperFactory = dataMapperFactory; _parent = (TParent)parent; } public override void LazyLoad() { if (!IsLoaded) { if (_condition != null && _condition(_parent)) { using (IDataMapper db = _dbMapperFactory()) { _value = _query(db, _parent); } } else { _value = default(TChild); } IsLoaded = true; } } public static implicit operator LazyLoaded(TChild val) { return new LazyLoaded(val); } public static implicit operator TChild(LazyLoaded lazy) { return lazy.Value; } } }