Permalink
Browse files

New UberMemoizer class makes it super simple to memoize many function…

…s without having to keep multiple memoizers around.
  • Loading branch information...
1 parent ab6543d commit 9c42c3d61e83a3b2c20d3c0579b2a8165f143845 @rmoritz committed Mar 2, 2013
View
2 .gitignore
@@ -1,4 +1,4 @@
-**~
+*~
*.suo
bin
obj
View
4 Examples/Factory/Examples.Factory.csproj → Examples/Uber/Examples.Uber.csproj
@@ -7,8 +7,8 @@
<ProjectGuid>{592FD4FE-AB9B-4C91-B712-5278E8869993}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>Examples.Factory</RootNamespace>
- <AssemblyName>Examples.Factory</AssemblyName>
+ <RootNamespace>Examples.Uber</RootNamespace>
+ <AssemblyName>Examples.Uber</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
View
15 Examples/Factory/Program.cs → Examples/Uber/Program.cs
@@ -6,7 +6,7 @@
using System.Threading.Tasks;
using Recall;
-namespace Examples.Factory
+namespace Examples.Uber
{
internal class Program
{
@@ -42,18 +42,7 @@ private static void Main()
{
Console.WriteLine("Executing queries. Please be patient.");
- var factory = new MemoizerFactory
- {
- GenericCacheType = typeof(Dictionary<,>),
- Settings = new MemoizerSettings
- {
- MaxAge = TimeSpan.FromSeconds(5),
- MaxItems = 10000
- }
- };
-
- var memoizer = factory.Create<int>();
- var memoizedTaskAsyncFunc = memoizer.MemoizeTask<int>(TaskAsyncQuery);
+ var memoizedTaskAsyncFunc = UberMemoizer.DefaultInstance.MemoizeTask<int, int>(TaskAsyncQuery);
ExecuteTaskAsyncQuery(memoizedTaskAsyncFunc, QueryArg).Wait();
ExecuteTaskAsyncQuery(memoizedTaskAsyncFunc, QueryArg).Wait();
View
10 Examples/Factory/Properties/AssemblyInfo.cs → Examples/Uber/Properties/AssemblyInfo.cs
@@ -5,12 +5,12 @@
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
-[assembly: AssemblyTitle("Examples.Factory")]
-[assembly: AssemblyDescription("")]
+[assembly: AssemblyTitle("Examples.Uber")]
+[assembly: AssemblyDescription("Part of Recall, a memoization library for .NET")]
[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Examples.Factory")]
-[assembly: AssemblyCopyright("Copyright © 2013")]
+[assembly: AssemblyCompany("Ralph Möritz")]
+[assembly: AssemblyProduct("Recall")]
+[assembly: AssemblyCopyright("Copyright © Ralph Möritz 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
View
3 README.md
@@ -16,8 +16,7 @@ static void Main()
{
Console.WriteLine("Executing queries. Please be patient.");
- var memoizer = new Memoizer<int, Dictionary<string, CacheEntry<int>>>();
- var memoizedTaskAsyncFunc = memoizer.MemoizeTask<int>(TaskAsyncQuery);
+ var memoizedTaskAsyncFunc = UberMemoizer.DefaultInstance.MemoizeTask<int, int>(TaskAsyncQuery);
ExecuteTaskAsyncQuery(memoizedTaskAsyncFunc, QueryArg).Wait();
ExecuteTaskAsyncQuery(memoizedTaskAsyncFunc, QueryArg).Wait();
View
2 Recall.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>Recall</id>
- <version>1.0.2</version>
+ <version>1.0.3</version>
<authors>Ralph Möritz</authors>
<owners>Ralph Möritz</owners>
<projectUrl>https://github.com/ralph-moeritz/Recall</projectUrl>
View
2 Recall.sln
@@ -29,7 +29,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{93DB80
.nuget\NuGet.targets = .nuget\NuGet.targets
EndProjectSection
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples.Factory", "Examples\Factory\Examples.Factory.csproj", "{592FD4FE-AB9B-4C91-B712-5278E8869993}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples.Uber", "Examples\Uber\Examples.Uber.csproj", "{592FD4FE-AB9B-4C91-B712-5278E8869993}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
View
50 Recall/Defaults.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Recall
+{
+ internal class Defaults
+ {
+ public static Type DefaultGenericCacheType
+ {
+ get { return typeof(Dictionary<,>); }
+ }
+
+ public static MemoizerSettings DefaultMemoizerSettings
+ {
+ get
+ {
+ return new MemoizerSettings
+ {
+ MaxAge = TimeSpan.FromMinutes(5),
+ MaxItems = 10000
+ };
+ }
+ }
+
+ public static IMemoizerFactory DefaultMemoizerFactory
+ {
+ get
+ {
+ return new MemoizerFactory
+ {
+ GenericCacheType = DefaultGenericCacheType,
+ Settings = DefaultMemoizerSettings
+ };
+ }
+ }
+
+ public static IUberMemoizer DefaultUberMemoizer
+ {
+ get
+ {
+ return new UberMemoizer
+ {
+ Factory = DefaultMemoizerFactory
+ };
+ }
+ }
+ }
+}
View
15 Recall/IMemoizer.cs
@@ -5,6 +5,21 @@
namespace Recall
{
+ public interface IMemoizer
+ {
+ MemoizedFunc<TResult> Memoize<TResult>(Func<IEnumerable<TResult>> func);
+
+ MemoizedFunc<TArg, TResult> Memoize<TArg, TResult>(Func<TArg, IEnumerable<TResult>> func);
+
+ MemoizedAsyncFunc<TResult> Memoize<TResult>(Action<Action<IEnumerable<TResult>>> action);
+
+ MemoizedAsyncFunc<TArg, TResult> Memoize<TArg, TResult>(Action<TArg, Action<IEnumerable<TResult>>> action);
+
+ MemoizedTaskAsyncFunc<TResult> MemoizeTask<TResult>(Func<Task<IEnumerable<TResult>>> func);
+
+ MemoizedTaskAsyncFunc<TArg, TResult> MemoizeTask<TArg, TResult>(Func<TArg, Task<IEnumerable<TResult>>> func);
+ }
+
public interface IMemoizer<TResult>
{
MemoizerSettings Settings { get; set; }
View
12 Recall/IUberMemoizer.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Recall
+{
+ public interface IUberMemoizer : IMemoizer
+ {
+ IMemoizerFactory Factory { get; set; }
+ }
+}
View
39 Recall/Memoizer.cs
@@ -13,28 +13,31 @@ public sealed class Memoizer<TResult, TCache> : IMemoizer<TResult>
public static readonly Func<IEnumerable<KeyValuePair<string, CacheEntry<TResult>>>,
IOrderedEnumerable<KeyValuePair<string, CacheEntry<TResult>>>> DefaultEvictionOrderer = EvictionPolicy.LRU;
- private static readonly MemoizerSettings DefaultSettings = new MemoizerSettings
- {
- MaxAge = TimeSpan.FromMinutes(5),
- MaxItems = 10000
- };
- private static Memoizer<TResult, TCache> _defaultInstance;
#endregion
#region Fields
private readonly TCache _cache = new TCache();
private readonly object _locker = new object();
+ private MemoizerSettings _settings = Defaults.DefaultMemoizerSettings;
+
+ public Func<IEnumerable<KeyValuePair<string, CacheEntry<TResult>>>,
+ IOrderedEnumerable<KeyValuePair<string, CacheEntry<TResult>>>> EvictionOrderer { get; set; }
#endregion
- #region Implementation of IMemoizer
+ #region Properties
+
+ public MemoizerSettings Settings
+ {
+ get { return _settings; }
+ set { _settings = value; }
+ }
- public MemoizerSettings Settings { get; set; }
+ #endregion
- public Func<IEnumerable<KeyValuePair<string, CacheEntry<TResult>>>,
- IOrderedEnumerable<KeyValuePair<string, CacheEntry<TResult>>>> EvictionOrderer { get; set; }
+ #region Public Methods
public MemoizedFunc<TResult> Memoize(Func<IEnumerable<TResult>> func)
{
@@ -343,21 +346,7 @@ public MemoizedTaskAsyncFunc<TResult> MemoizeTask(Func<Task<IEnumerable<TResult>
#endregion
- #region Utility Functions
-
- public static Memoizer<TResult, TCache> DefaultInstance
- {
- get { return _defaultInstance ?? CreateDefaultInstance(); }
- }
-
- private static Memoizer<TResult, TCache> CreateDefaultInstance()
- {
- _defaultInstance = new Memoizer<TResult, TCache>
- {
- Settings = DefaultSettings
- };
- return _defaultInstance;
- }
+ #region Private Methods
private void Invalidate(string key)
{
View
39 Recall/MemoizerFactory.cs
@@ -4,21 +4,46 @@ namespace Recall
{
public sealed class MemoizerFactory : IMemoizerFactory
{
+ #region Static Fields
+
+ public static IMemoizerFactory DefaultInstance = Defaults.DefaultMemoizerFactory;
+
private static readonly Type GenericMemoizerType = typeof(Memoizer<,>);
- #region Implementation of IMemoizerFactory
+ #endregion
+
+ #region Fields
+
+ private MemoizerSettings _settings = Defaults.DefaultMemoizerSettings;
+ private Type _genericCacheType = Defaults.DefaultGenericCacheType;
+
+ #endregion
+
+ #region Properties
- public MemoizerSettings Settings { get; set; }
+ public MemoizerSettings Settings
+ {
+ get { return _settings; }
+ set { _settings = value; }
+ }
+
+ public Type GenericCacheType
+ {
+ get { return _genericCacheType; }
+ set { _genericCacheType = value; }
+ }
+
+ #endregion
- public Type GenericCacheType { get; set; }
+ #region Public Methods
- public IMemoizer<T> Create<T>()
+ public IMemoizer<TResult> Create<TResult>()
{
- var constructedCacheType = GenericCacheType.MakeGenericType(typeof(string), typeof (CacheEntry<T>));
- var constructedMemoizerType = GenericMemoizerType.MakeGenericType(typeof (T), constructedCacheType);
+ var constructedCacheType = GenericCacheType.MakeGenericType(typeof(string), typeof (CacheEntry<TResult>));
+ var constructedMemoizerType = GenericMemoizerType.MakeGenericType(typeof (TResult), constructedCacheType);
var ctor = constructedMemoizerType.GetConstructor(new Type[]{});
- var memoizer = (IMemoizer<T>)ctor.Invoke(null);
+ var memoizer = (IMemoizer<TResult>) ctor.Invoke(null);
memoizer.Settings = Settings;
return memoizer;
}
View
3 Recall/Recall.csproj
@@ -38,14 +38,17 @@
</ItemGroup>
<ItemGroup>
<Compile Include="CacheEntry.cs" />
+ <Compile Include="Defaults.cs" />
<Compile Include="EvictionPolicy.cs" />
<Compile Include="IMemoizer.cs" />
<Compile Include="IMemoizerFactory.cs" />
+ <Compile Include="IUberMemoizer.cs" />
<Compile Include="MemoizedFunc.cs" />
<Compile Include="Memoizer.cs" />
<Compile Include="MemoizerFactory.cs" />
<Compile Include="MemoizerSettings.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="UberMemoizer.cs" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<PropertyGroup>
View
90 Recall/UberMemoizer.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Recall
+{
+ public sealed class UberMemoizer : IUberMemoizer
+ {
+ #region Static Fields
+
+ public static readonly IUberMemoizer DefaultInstance = Defaults.DefaultUberMemoizer;
+
+ #endregion
+
+ #region Fields
+
+ private IDictionary<Type, object> _memoizers = new Dictionary<Type, object>();
+ private IMemoizerFactory _factory = Defaults.DefaultMemoizerFactory;
+
+ #endregion
+
+ #region Properties
+
+ public IMemoizerFactory Factory
+ {
+ get { return _factory; }
+ set { _factory = value; }
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ public MemoizedFunc<TResult> Memoize<TResult>(Func<IEnumerable<TResult>> func)
+ {
+ var memoizer = GetMemoizer<TResult>();
+ return memoizer.Memoize(func);
+ }
+
+ public MemoizedFunc<TArg, TResult> Memoize<TArg, TResult>(Func<TArg, IEnumerable<TResult>> func)
+ {
+ var memoizer = GetMemoizer<TResult>();
+ return memoizer.Memoize<TArg>(func);
+ }
+
+ public MemoizedAsyncFunc<TResult> Memoize<TResult>(Action<Action<IEnumerable<TResult>>> action)
+ {
+ var memoizer = GetMemoizer<TResult>();
+ return memoizer.Memoize(action);
+ }
+
+ public MemoizedAsyncFunc<TArg, TResult> Memoize<TArg, TResult>(Action<TArg, Action<IEnumerable<TResult>>> action)
+ {
+ var memoizer = GetMemoizer<TResult>();
+ return memoizer.Memoize<TArg>(action);
+ }
+
+ public MemoizedTaskAsyncFunc<TResult> MemoizeTask<TResult>(Func<Task<IEnumerable<TResult>>> func)
+ {
+ var memoizer = GetMemoizer<TResult>();
+ return memoizer.MemoizeTask(func);
+ }
+
+ public MemoizedTaskAsyncFunc<TArg, TResult> MemoizeTask<TArg, TResult>(Func<TArg, Task<IEnumerable<TResult>>> func)
+ {
+ var memoizer = GetMemoizer<TResult>();
+ return memoizer.MemoizeTask<TArg>(func);
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ private IMemoizer<TResult> GetMemoizer<TResult>()
+ {
+ var t = typeof (TResult);
+ object memoizer;
+ if (!_memoizers.TryGetValue(t, out memoizer))
+ {
+ memoizer = Factory.Create<TResult>();
+ _memoizers.Add(t, memoizer);
+ }
+ return (IMemoizer<TResult>) memoizer;
+ }
+
+ #endregion
+ }
+}

0 comments on commit 9c42c3d

Please sign in to comment.