diff --git a/HandsetDetectionAPI/HDCache.cs b/HandsetDetectionAPI/HDCache.cs index 088b30b7..0b23fcda 100644 --- a/HandsetDetectionAPI/HDCache.cs +++ b/HandsetDetectionAPI/HDCache.cs @@ -1,10 +1,14 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; +using System.IO; using System.Linq; using System.Runtime.Caching; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Threading.Tasks; +using System.Web; using System.Web.Caching; using System.Web.Script.Serialization; @@ -13,20 +17,15 @@ namespace HandsetDetectionAPI public class HdCache { private static int _maxJsonLength = 40000000; - string _prefix = "hd4-"; + string _prefix = "hd4_"; //int duration = 7200; - ObjectCache _myCache; + readonly MemoryCache _myCache = MemoryCache.Default; CacheItemPolicy _policy = new CacheItemPolicy(); JavaScriptSerializer _jss = new JavaScriptSerializer { MaxJsonLength = _maxJsonLength }; public HdCache() { _policy.AbsoluteExpiration = new DateTimeOffset(DateTime.Now.AddHours(24)); - NameValueCollection cacheSettings = new NameValueCollection(3) - { - {"CacheMemoryLimitMegabytes", Convert.ToString(200)} - }; - _myCache = MemoryCache.Default; } public T Write(string key, T value) @@ -36,7 +35,7 @@ public T Write(string key, T value) { if (value != null && key != "") { - // string storethis = _jss.Serialize(value); + // var count = _myCache.Count(); _myCache.Set(_prefix + key, value, _policy); return value; } @@ -58,7 +57,13 @@ public T Read(string key) try { object fromCache = _myCache.Get(_prefix + key); - if (fromCache != null) return (T)Convert.ChangeType(fromCache, typeof(T)); + + + if (fromCache != null) + { + T item = (T)Convert.ChangeType(fromCache, typeof(T)); + return item.Clone(); + } } catch (Exception) { @@ -86,4 +91,39 @@ public bool Purge() } } + + /// + /// Provides a method for performing a deep copy of an object. + /// Binary Serialization is used to perform the copy. + /// + public static class ObjectCopier + { + /// + /// Perform a deep Copy of the object. + /// + /// The type of object being copied. + /// The object instance to copy./// The copied object. + public static T Clone(this T source) + { + if (!typeof(T).IsSerializable) + { + throw new ArgumentException("The type must be serializable.", "source"); + } + + // Don't serialize a null object, simply return the default for that object + if (Object.ReferenceEquals(source, null)) + { + return default(T); + } + + IFormatter formatter = new BinaryFormatter(); + Stream stream = new MemoryStream(); + using (stream) + { + formatter.Serialize(stream, source); + stream.Seek(0, SeekOrigin.Begin); + return (T)formatter.Deserialize(stream); + } + } + } } diff --git a/HandsetDetectionAPI/HDDevice.cs b/HandsetDetectionAPI/HDDevice.cs index 83717def..7a0946d1 100644 --- a/HandsetDetectionAPI/HDDevice.cs +++ b/HandsetDetectionAPI/HDDevice.cs @@ -318,7 +318,7 @@ public Dictionary FindRating(string deviceId, Dictionarystring specsField : Either "platform', 'browser', 'language' /// /// - public void SpecsOverlay(string specsField, ref dynamic device, Dictionary specs) + public Dictionary SpecsOverlay(string specsField, Dictionary device, Dictionary specs) { switch (specsField) { @@ -361,6 +361,7 @@ public void SpecsOverlay(string specsField, ref dynamic device, Dictionary @@ -406,11 +407,12 @@ private Dictionary InfoStringToArray(string hardwareInfo) /// /// /// - private void HardwareInfoOverlay(ref dynamic device, Dictionary infoArray) + private Dictionary HardwareInfoOverlay(Dictionary device, Dictionary infoArray) { device["Device"]["hd_ops"]["display_x"] = infoArray["display_x"]; device["Device"]["hd_ops"]["display_y"] = infoArray["display_y"]; device["Device"]["hd_ops"]["display_pixel_ratio"] = infoArray["display_pixel_ratio"]; + return device; } /// @@ -425,7 +427,7 @@ private void HardwareInfoOverlay(ref dynamic device, Dictionary /// /// /// array The matched device or null if not found - private dynamic MatchDevice(Dictionary headers) + private Dictionary MatchDevice(Dictionary headers) { // Opera mini sometimes puts the vendor # model in the header - nice! ... sometimes it puts ? # ? in as well if (headers.ContainsKey("x-operamini-phone") && headers["x-operamini-phone"].ToString() != "? # ?") @@ -494,7 +496,7 @@ private dynamic MatchDevice(Dictionary headers) return this.FindById(itemid); } - return false; + return null; } /// @@ -558,7 +560,9 @@ public dynamic V4MatchBuildInfo(Dictionary buildInfo) // Platform Detection dynamic platform = V4MatchBiHelper(buildInfo, "platform"); if (platform != null && platform.Count != 0) - this.SpecsOverlay("platform", ref device, platform["Extra"]); + { + device = this.SpecsOverlay("platform", device, platform["Extra"]); + } Reply["hd_specs"] = device["Device"]["hd_specs"]; return SetError(0, "OK"); @@ -695,9 +699,9 @@ private dynamic V4MatchHttpHeaders(Dictionary headers, string h } } - dynamic device = MatchDevice(deviceHeaders); + Dictionary device = MatchDevice(deviceHeaders); - if (device is bool) + if (device == null) { return SetError(301, "Not Found"); } @@ -715,7 +719,7 @@ private dynamic V4MatchHttpHeaders(Dictionary headers, string h { if (hwProps is IDictionary) { - HardwareInfoOverlay(ref device, (Dictionary)hwProps); + device = HardwareInfoOverlay(device, (Dictionary)hwProps); } } @@ -725,10 +729,10 @@ private dynamic V4MatchHttpHeaders(Dictionary headers, string h } // Get extra info - dynamic platform = _extra.MatchExtra("platform", extraHeaders); - dynamic browser = _extra.MatchExtra("browser", extraHeaders); - dynamic app = _extra.MatchExtra("app", extraHeaders); - dynamic language = _extra.MatchLanguage(extraHeaders); + Dictionary platform = _extra.MatchExtra("platform", extraHeaders); + Dictionary browser = _extra.MatchExtra("browser", extraHeaders); + Dictionary app = _extra.MatchExtra("app", extraHeaders); + Dictionary language = _extra.MatchLanguage(extraHeaders); // Find out if there is any contention on the detected rule. dynamic deviceList = GetHighAccuracyCandidates(); @@ -737,14 +741,14 @@ private dynamic V4MatchHttpHeaders(Dictionary headers, string h { List pass1List = new List(); // Resolve contention with OS check - if (!(platform is bool)) + if (platform != null) { _extra.Set(platform); foreach (dynamic item in deviceList) { - dynamic tryDevice = this.FindById(item); + Dictionary tryDevice = this.FindById(item); if (_extra.VerifyPlatform(tryDevice["Device"]["hd_specs"])) { @@ -772,7 +776,7 @@ private dynamic V4MatchHttpHeaders(Dictionary headers, string h // Sort the results //usort($result, array($this, 'hd_sortByScore')); Dictionary bestRatedDevice = GetDeviceFromRatingResult(result); - dynamic objDevice = this.FindById(bestRatedDevice["_id"]); + Dictionary objDevice = this.FindById(bestRatedDevice["_id"]); if (objDevice.Count > 0) { device = objDevice; @@ -782,25 +786,27 @@ private dynamic V4MatchHttpHeaders(Dictionary headers, string h } // Overlay specs - if (!(platform is bool)) + if (platform != null) { - SpecsOverlay("platform", ref device, platform["Extra"]); + device = SpecsOverlay("platform", device, platform["Extra"]); } - if (!(browser is bool)) + if (browser != null) { - SpecsOverlay("browser", ref device, browser["Extra"]); + device = SpecsOverlay("browser", device, browser["Extra"]); } - if (!(app is bool)) + if (app != null) { - SpecsOverlay("app", ref device, app["Extra"]); + device = SpecsOverlay("app", device, app["Extra"]); } - if (!(language is bool)) + if (language != null) { - SpecsOverlay("language", ref device, language["Extra"]); + device = SpecsOverlay("language", device, language["Extra"]); } // Overlay hardware info result if required if (device["Device"]["hd_ops"]["overlay_result_specs"].ToString() == "1" && !string.IsNullOrEmpty(hardwareInfo)) - HardwareInfoOverlay(ref device, hwProps); + { + device = HardwareInfoOverlay(device, hwProps); + } Reply["hd_specs"] = device["Device"]["hd_specs"]; return SetError(0, "OK");//for meantime diff --git a/HandsetDetectionAPI/HDExtra.cs b/HandsetDetectionAPI/HDExtra.cs index 30a6a1f2..243a14af 100644 --- a/HandsetDetectionAPI/HDExtra.cs +++ b/HandsetDetectionAPI/HDExtra.cs @@ -51,7 +51,7 @@ public dynamic MatchExtra(string className, Dictionary headers) return extra; } } - return false; + return null; } @@ -71,7 +71,7 @@ public dynamic FindById(string id) /// /// headers A key => value array of sanitized http headers /// array Extra on success, false otherwise - public dynamic MatchLanguage(Dictionary headers) + public Dictionary MatchLanguage(Dictionary headers) { Dictionary extra = new Dictionary(); // Mock up a fake Extra for merge into detection reply. diff --git a/HandsetDetectionAPI/HDStore.cs b/HandsetDetectionAPI/HDStore.cs index b878791c..f8e45564 100644 --- a/HandsetDetectionAPI/HDStore.cs +++ b/HandsetDetectionAPI/HDStore.cs @@ -130,7 +130,7 @@ public bool store(string key, Dictionary data) /// boolean true on success, false public T Read(string key) { - var reply = _cache.Read(key); + T reply = _cache.Read(key); if (reply != null) return reply; @@ -138,7 +138,7 @@ public T Read(string key) if (reply != null) { _cache.Write(key, reply); - return reply; + return reply.Clone(); } else {