public static Func <FastDictionary2 <TKey, TValue> > CreateFastDictionary2Generator <TKey, TValue>( this IEqualityComparerExpression <TKey> comparerExp, int capacity, Func <TKey, TKey, bool> equalsFunc, Func <TKey, int> getHashCodeFunc, QueryContainer container) { if (EqualityComparerExpression <TKey> .IsSimpleDefault(comparerExp)) { return(() => new FastDictionary2 <TKey, TValue>()); } if (container == null) { return(() => new FastDictionary2 <TKey, TValue>(capacity, equalsFunc, getHashCodeFunc)); } var equalsExp = comparerExp.GetEqualsExpr(); var getHashCodeExp = comparerExp.GetGetHashCodeExpr(); var vars = VariableFinder.Find(equalsExp).Select(o => o.GetHashCode()).ToList(); if (!vars.Any()) { vars.Add(string.Empty.StableHash()); } var hashvars = VariableFinder.Find(getHashCodeExp).Select(o => o.GetHashCode()).ToList(); if (!hashvars.Any()) { hashvars.Add(string.Empty.StableHash()); } var key = Tuple.Create( equalsExp.ToString() + getHashCodeExp.ToString() + string.Concat(vars.Aggregate((a, i) => a ^ i)) + string.Concat(hashvars.Aggregate((a, i) => a ^ i)), typeof(TKey), typeof(TValue)); Type temp; lock (sentinel) { if (!generatorCache.TryGetValue(key, out temp)) { string typeName = Prefix + classCounter++; var builderCode = new GeneratedFastDictionary(typeName, "2").TransformText(); var a = Transformer.CompileSourceCode(builderCode, Array.Empty <Assembly>(), out string errorMessages); temp = a.GetType(typeName + "`2"); temp = temp.MakeGenericType(typeof(TKey), typeof(TValue)); MethodInfo init = temp.GetTypeInfo().GetMethod("Initialize", BindingFlags.Static | BindingFlags.Public); init.Invoke(null, new object[] { equalsFunc, getHashCodeFunc, capacity }); generatorCache.Add(key, temp); } if (!container.TryGetFastDictionary2Type(key, out Type other)) { container.RegisterFastDictionary2Type(key, temp); } } return(() => (FastDictionary2 <TKey, TValue>)Activator.CreateInstance(temp)); }
public static Expression <Func <SortedDictionary <TKey, TValue> > > CreateSortedDictionaryGenerator <TKey, TValue>(this IComparerExpression <TKey> comparerExp, QueryContainer container) { if (ComparerExpression <TKey> .IsSimpleDefault(comparerExp)) { return(() => new SortedDictionary <TKey, TValue>()); } var expr = comparerExp.GetCompareExpr(); if (container == null) { Expression <Func <Comparison <TKey>, SortedDictionary <TKey, TValue> > > template = (c) => new SortedDictionary <TKey, TValue>(Comparer <TKey> .Create(c)); var replaced = template.ReplaceParametersInBody(expr); return(Expression.Lambda <Func <SortedDictionary <TKey, TValue> > >(replaced)); } var expression = expr.ToString(); var vars = VariableFinder.Find(expr).Select(o => o.GetHashCode()); var captures = vars.Aggregate(expression.GetHashCode(), (a, i) => a ^ i); var key = Tuple.Create(expression + string.Concat(vars.Select(o => o.ToString(CultureInfo.InvariantCulture))), typeof(TKey), typeof(TValue)); Type temp; lock (sentinel) { if (!DictionaryTypes.TryGetValue(key, out temp)) { string typeName = Prefix + captures.ToString(CultureInfo.InvariantCulture) + typeof(TKey).ToString().GetHashCode().ToString(CultureInfo.InvariantCulture) + typeof(TValue).ToString().GetHashCode().ToString(CultureInfo.InvariantCulture); typeName = typeName.Replace("-", "_"); var builderCode = new GeneratedSortedDictionary(typeName).TransformText(); var assemblyReferences = Transformer.AssemblyReferencesNeededFor(typeof(SortedDictionary <,>)); var a = Transformer.CompileSourceCode(builderCode, assemblyReferences, out string errorMessages); temp = a.GetType(typeName + "`2"); temp = temp.MakeGenericType(typeof(TKey), typeof(TValue)); var init = temp.GetTypeInfo().GetMethod("Initialize", BindingFlags.Static | BindingFlags.Public); init.Invoke(null, new object[] { Comparer <TKey> .Create(expr.Compile()) }); DictionaryTypes.Add(key, temp); } if (!container.TryGetSortedDictionaryType(key, out Type other)) { container.RegisterSortedDictionaryType(key, temp); } } return(Expression.Lambda <Func <SortedDictionary <TKey, TValue> > >(Expression.New(temp))); }