public static MethodInfo GetHashMethod(EnumMatcherMode mode) { switch (mode) { case EnumMatcherMode.One: return(Methods.EnumHash1); case EnumMatcherMode.Two: return(Methods.EnumHash2); case EnumMatcherMode.Four: return(Methods.EnumHash4); case EnumMatcherMode.Eight: return(Methods.EnumHash8); case EnumMatcherMode.Sixteen: return(Methods.EnumHash16); case EnumMatcherMode.ThirtyTwo: return(Methods.EnumHash32); case EnumMatcherMode.SixtyFour: return(Methods.EnumHash64); default: throw new Exception("Unexpected EnumMatcherMode: " + mode); } }
static bool MakeEnumMatcher(out Dictionary <string, object> enumLookup, out Dictionary <string, int> memberToBucket, out Dictionary <string, uint> memberToHash, out EnumMatcherMode bestMode) { var forType = typeof(EnumType); var allValues = Enum.GetValues(forType); enumLookup = allValues.Cast <EnumType>().ToDictionary(e => forType.GetEnumValueName(e), e => Convert.ChangeType(e, Enum.GetUnderlyingType(forType))); var enumNames = enumLookup.Keys; var allModes = Enum.GetValues(typeof(EnumMatcherMode)) .Cast <EnumMatcherMode>() .Where(m => m != EnumMatcherMode.None) .OrderBy(o => (int)o) .ToList(); foreach (var mode in allModes) { var mToH = new Dictionary <string, uint>(); var method = GetHashMethod(mode); var buckets = enumNames.GroupBy( m => { using (var str = new StringReader("\"" + m.JsonEscape(jsonp: false) + "\"")) { str.Read(); // skip " var ps = new object[] { str, (int)-1, (uint)0 }; method.Invoke(null, ps); var bucket = (int)ps[1]; var hash = (uint)ps[2]; mToH[m] = hash; return(bucket); } } ); var collisions = buckets.Any(g => g.Count() > 1); if (collisions) { continue; } memberToHash = mToH; memberToBucket = buckets.ToDictionary(d => d.Single(), d => d.Key); bestMode = mode; return(true); } memberToHash = null; memberToBucket = null; bestMode = EnumMatcherMode.None; return(false); }