Skip to content

Commit

Permalink
Added caching option
Browse files Browse the repository at this point in the history
  • Loading branch information
jameskimsca committed Aug 24, 2018
1 parent db56937 commit 6446299
Show file tree
Hide file tree
Showing 18 changed files with 345 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,8 @@
<PerplexRecaptchConfig>
<ErrorMessage />
</PerplexRecaptchConfig>
<PerplexCacheConfig>
<EnableCache>true</EnableCache>
<CacheDurationInMinutes>10</CacheDurationInMinutes>
</PerplexCacheConfig>
</PerplexUmbracoFormsConfig>
48 changes: 48 additions & 0 deletions Perplex.Umbraco.Forms/Code/ArrayExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;

namespace PerplexUmbraco.Forms.Code
{
public static class ArrayExtensions
{
public static void ForEach(this Array array, Action<Array, int[]> action)
{
if (array.LongLength == 0) return;
ArrayTraverse walker = new ArrayTraverse(array);
do action(array, walker.Position);
while (walker.Step());
}
}

internal class ArrayTraverse
{
public int[] Position;
private int[] maxLengths;

public ArrayTraverse(Array array)
{
maxLengths = new int[array.Rank];
for (int i = 0; i < array.Rank; ++i)
{
maxLengths[i] = array.GetLength(i) - 1;
}
Position = new int[array.Rank];
}

public bool Step()
{
for (int i = 0; i < Position.Length; ++i)
{
if (Position[i] < maxLengths[i])
{
Position[i]++;
for (int j = 0; j < i; j++)
{
Position[j] = 0;
}
return true;
}
}
return false;
}
}
}
71 changes: 71 additions & 0 deletions Perplex.Umbraco.Forms/Code/CacheService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System;

using Umbraco.Core;
using Umbraco.Core.Logging;

namespace PerplexUmbraco.Forms.Code
{
public class CacheService : ICacheService
{
public void SetRequestCache(string cacheKey, object cacheObject)
{
if (cacheObject != null)
{
ApplicationContext.Current.ApplicationCache.RequestCache.GetCacheItem(cacheKey, () => cacheObject);
return;
}

LogHelper.Warn<CacheService>($"Failed to cache null object with key: {cacheKey}");
}

public T GetRequestCache<T>(string cacheKey)
{
var cachedObject = ApplicationContext.Current.ApplicationCache.RequestCache.GetCacheItem(cacheKey);

if (cachedObject == null)
{
return default(T);
}

return (T)cachedObject;
}

public void SetRuntimeCache(string cacheKey, object cacheObject, TimeSpan duration)
{
SetRuntimeCache(cacheKey, cacheObject, duration, false);
}

public void SetRuntimeCache(string cacheKey, object cacheObject, TimeSpan duration, bool isSliding)
{
if (cacheObject != null)
{
ApplicationContext.Current.ApplicationCache.RuntimeCache.InsertCacheItem(cacheKey, cacheObject.Copy, duration, isSliding);
return;
}

LogHelper.Warn<CacheService>($"Failed to cache null object with key: {cacheKey}");
}

public void ClearRuntimeCacheByKey(string cacheKey)
{
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(cacheKey);
}

public void ClearRuntimeCacheByPrefix(string prefix)
{
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(prefix);
}

public T GetRuntimeCache<T>(string cacheKey)
{
var cachedObject = ApplicationContext.Current.ApplicationCache.RuntimeCache.GetCacheItem(cacheKey);

if (cachedObject == null)
{
return default(T);
}

return ((T)cachedObject).Copy();
}
}
}
7 changes: 1 addition & 6 deletions Perplex.Umbraco.Forms/Code/Configuration/ExtensionConfig.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using System.Xml.Serialization;

namespace PerplexUmbraco.Forms.Code.Configuration
{
Expand Down
4 changes: 0 additions & 4 deletions Perplex.Umbraco.Forms/Code/Configuration/FieldTypeConfig.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace PerplexUmbraco.Forms.Code.Configuration
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace PerplexUmbraco.Forms.Code.Configuration
Expand Down
14 changes: 14 additions & 0 deletions Perplex.Umbraco.Forms/Code/Configuration/PerplexCacheConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Xml.Serialization;

namespace PerplexUmbraco.Forms.Code.Configuration
{
[XmlType("PerplexCacheConfig")]
public class PerplexCacheConfig
{
[XmlElement("CacheDurationInMinutes")]
public int CacheDurationInMinutes { get; set; }

[XmlElement("EnableCache")]
public bool EnableCache { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using System.Xml.Serialization;

namespace PerplexUmbraco.Forms.Code.Configuration
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using System.Xml.Serialization;

namespace PerplexUmbraco.Forms.Code.Configuration
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using System.Xml.Serialization;

namespace PerplexUmbraco.Forms.Code.Configuration
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Hosting;
using System.Xml.Serialization;

using static PerplexUmbraco.Forms.Code.Constants;

namespace PerplexUmbraco.Forms.Code.Configuration
Expand Down Expand Up @@ -73,6 +71,8 @@ public static void CreateIfNotExists()

public PerplexRecaptchaConfig PerplexRecaptchaConfig { get; set; }

public PerplexCacheConfig PerplexCacheConfig { get; set; }

private static string GetFilePath()
{
return HostingEnvironment.MapPath(Constants.CONFIGURATION_FILE_PATH);
Expand Down Expand Up @@ -139,6 +139,12 @@ private static string GetFilePath()
PerplexRecaptchaConfig = new PerplexRecaptchaConfig
{
ErrorMessage = ""
},

PerplexCacheConfig = new PerplexCacheConfig
{
EnableCache = false,
CacheDurationInMinutes = 10
}
};
}
Expand Down
15 changes: 15 additions & 0 deletions Perplex.Umbraco.Forms/Code/ICacheService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;

namespace PerplexUmbraco.Forms.Code
{
public interface ICacheService
{
T GetRequestCache<T>(string cacheKey);
void SetRequestCache(string cacheKey, object cacheObject);
T GetRuntimeCache<T>(string cacheKey);
void SetRuntimeCache(string cacheKey, object cacheObject, TimeSpan duration);
void SetRuntimeCache(string cacheKey, object cacheObject, TimeSpan duration, bool isSliding);
void ClearRuntimeCacheByKey(string cacheKey);
void ClearRuntimeCacheByPrefix(string prefix);
}
}
104 changes: 104 additions & 0 deletions Perplex.Umbraco.Forms/Code/ObjectExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.Reflection;

using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace PerplexUmbraco.Forms.Code
{
public static class ObjectExtensions
{
private static readonly MethodInfo CloneMethod = typeof(Object).GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance);

public static bool IsPrimitive(this Type type)
{
if (type == typeof(String)) return true;
return (type.IsValueType & type.IsPrimitive);
}

public static Object Copy(this Object originalObject)
{
return InternalCopy(originalObject, new Dictionary<Object, Object>(new ReferenceEqualityComparer()));
}

public static T Copy<T>(this T original)
{
return (T)Copy((Object)original);
}

public static bool IsNullOrWhiteSpaceString(this object item)
{
return string.IsNullOrWhiteSpace(item?.ToString());
}

public static string ToJson(this object o, bool camelCase = false)
{
var settings = new JsonSerializerSettings();
if (camelCase)
{
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
}

return JsonConvert.SerializeObject(o, settings);
}

private static Object InternalCopy(Object originalObject, IDictionary<Object, Object> visited)
{
if (originalObject == null) return null;
var typeToReflect = originalObject.GetType();
if (IsPrimitive(typeToReflect)) return originalObject;
if (visited.ContainsKey(originalObject)) return visited[originalObject];
if (typeof(Delegate).IsAssignableFrom(typeToReflect)) return null;
var cloneObject = CloneMethod.Invoke(originalObject, null);
if (typeToReflect.IsArray)
{
var arrayType = typeToReflect.GetElementType();
if (IsPrimitive(arrayType) == false)
{
Array clonedArray = (Array)cloneObject;
clonedArray.ForEach((array, indices) => array.SetValue(InternalCopy(clonedArray.GetValue(indices), visited), indices));
}

}
visited.Add(originalObject, cloneObject);
CopyFields(originalObject, visited, cloneObject, typeToReflect);
RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect);
return cloneObject;
}

private static void RecursiveCopyBaseTypePrivateFields(object originalObject, IDictionary<object, object> visited, object cloneObject, Type typeToReflect)
{
if (typeToReflect.BaseType != null)
{
RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect.BaseType);
CopyFields(originalObject, visited, cloneObject, typeToReflect.BaseType, BindingFlags.Instance | BindingFlags.NonPublic, info => info.IsPrivate);
}
}

private static void CopyFields(object originalObject, IDictionary<object, object> visited, object cloneObject, Type typeToReflect, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy, Func<FieldInfo, bool> filter = null)
{
foreach (FieldInfo fieldInfo in typeToReflect.GetFields(bindingFlags))
{
if (filter != null && filter(fieldInfo) == false) continue;
if (IsPrimitive(fieldInfo.FieldType)) continue;
var originalFieldValue = fieldInfo.GetValue(originalObject);
var clonedFieldValue = InternalCopy(originalFieldValue, visited);
fieldInfo.SetValue(cloneObject, clonedFieldValue);
}
}
}

public class ReferenceEqualityComparer : EqualityComparer<Object>
{
public override bool Equals(object x, object y)
{
return ReferenceEquals(x, y);
}
public override int GetHashCode(object obj)
{
if (obj == null) return 0;
return obj.GetHashCode();
}
}
}
Loading

0 comments on commit 6446299

Please sign in to comment.