using System;
using NLog;
using NzbDrone.Common.Instrumentation;
namespace NzbDrone.Core.Datastore
{
public interface ILazyLoaded : ICloneable
{
bool IsLoaded { get; }
void Prepare(IDatabase database, 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 IsLoaded { get; protected set; }
public static implicit operator LazyLoaded(TChild val)
{
return new LazyLoaded(val);
}
public static implicit operator TChild(LazyLoaded lazy)
{
return lazy.Value;
}
public virtual void Prepare(IDatabase database, object parent)
{
}
public virtual void LazyLoad()
{
}
public object Clone()
{
return MemberwiseClone();
}
public bool ShouldSerializeValue()
{
return IsLoaded;
}
}
///
/// 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 static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(LazyLoaded));
private readonly Func _query;
private readonly Func _condition;
private IDatabase _database;
private TParent _parent;
public LazyLoaded(TChild val)
: base(val)
{
_value = val;
IsLoaded = true;
}
internal LazyLoaded(Func query, Func condition = null)
{
_query = query;
_condition = condition;
}
public static implicit operator LazyLoaded(TChild val)
{
return new LazyLoaded(val);
}
public static implicit operator TChild(LazyLoaded lazy)
{
return lazy.Value;
}
public override void Prepare(IDatabase database, object parent)
{
_database = database;
_parent = (TParent)parent;
}
public override void LazyLoad()
{
if (!IsLoaded)
{
if (_condition != null && _condition(_parent))
{
if (SqlBuilderExtensions.LogSql)
{
Logger.Trace($"Lazy loading {typeof(TChild)} for {typeof(TParent)}");
Logger.Trace("StackTrace: '{0}'", Environment.StackTrace);
}
_value = _query(_database, _parent);
}
else
{
_value = default;
}
IsLoaded = true;
}
}
}
}