Created
November 4, 2012 22:15
-
-
Save atheken/4014001 to your computer and use it in GitHub Desktop.
A lazy, but not too lazy, memoization class.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
namespace BlogUtils | |
{ | |
/// <summary> | |
/// An extension of "Lazy of T, but with the twist that it will | |
/// reload the resource at periodic intervals (and on request, of course). | |
/// </summary> | |
public class LazyEnough<T> | |
{ | |
private Func<T> _loader; | |
private DateTime _lastLoaded = DateTime.MinValue; | |
private Lazy<T> _lazyLoad; | |
private TimeSpan _reloadInterval; | |
public LazyEnough (Func<T> loader) : this(loader, new TimeSpan(0,0,1,0,0)) | |
{ | |
} | |
public LazyEnough (Func<T> loader, TimeSpan reloadInterval) | |
{ | |
_loader = loader; | |
_lazyLoad = new Lazy<T> (loader); | |
_reloadInterval = reloadInterval; | |
} | |
/// <summary> | |
/// Return the value, and if the timespan for reload has elapsed, let's refresh and return. | |
/// </summary> | |
/// <value> | |
/// The materialized value. | |
/// </value> | |
public T Value { | |
get { | |
return this.GetValue (); | |
} | |
} | |
/// <summary> | |
/// Is this class too lazy for you? You can force it to do some work by calling this method with "forceReload" true. | |
/// </summary> | |
/// <returns> | |
/// The refreshed value. | |
/// </returns> | |
public T GetValue (bool forceReload = false) | |
{ | |
var requestTime = DateTime.Now; | |
if (forceReload || _lastLoaded + _reloadInterval < requestTime) { | |
// it's possible that more than one "reload" could be requested and | |
// running on this line, but that would likely be the case under very high | |
// contention for this resource, and very short reload intervals. | |
// We could do fancy locks or interlocked code to avoid absolutely ALL "leaks", | |
// but here's an example where adding a bunch of code for "performance" ends up | |
// making maintainability more painful. | |
_lastLoaded = requestTime; | |
_lazyLoad = new Lazy<T> (_loader); | |
} | |
return _lazyLoad.Value; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ExpensiveResourceConsumer | |
{ | |
/// <summary> | |
/// A shared instance of the resource for all instances of the consumer. | |
/// </summary> | |
private static LazyEnough<ExpensiveResource> _resource; | |
public ExpensiveResourceConsumer () | |
{ | |
// if the resource hasn't been built yet, build it once, yes, this could potentially | |
// build multiple "LazyEnough<T>" classes, but seriously, object construction is CHEAP, | |
// and you'll note that it doesn't actually construct the ExpensiveResource. | |
_resource = _resource ?? new LazyEnough (() => new ExpensiveResource ()); | |
} | |
private class ExpensiveResource | |
{ | |
ExpensiveResource () | |
{ | |
//Does something expensive to construct itself. | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment