|
2 | 2 | using System.Collections.Generic;
|
3 | 3 | using System.Linq;
|
4 | 4 | using System.Linq.Expressions;
|
5 |
| -using System.Reflection; |
6 | 5 | using NHibernate.Linq.Visitors;
|
7 | 6 | using NHibernate.Util;
|
8 | 7 |
|
9 | 8 | namespace NHibernate.Linq
|
10 | 9 | {
|
11 | 10 | public class DmlExpressionRewriter
|
12 | 11 | {
|
13 |
| - static readonly ConstructorInfo DictionaryConstructorInfo = typeof(Dictionary<string, object>).GetConstructor(new[] {typeof(int)}); |
14 |
| - |
15 |
| - static readonly MethodInfo DictionaryAddMethodInfo = ReflectHelper.GetMethod<Dictionary<string, object>>(d => d.Add(null, null)); |
16 |
| - |
17 | 12 | readonly IReadOnlyCollection<ParameterExpression> _parameters;
|
18 | 13 | readonly Dictionary<string, Expression> _assignments = new Dictionary<string, Expression>();
|
19 | 14 |
|
@@ -80,39 +75,25 @@ void AddSettersFromAssignment(MemberAssignment assignment, string path)
|
80 | 75 | }
|
81 | 76 |
|
82 | 77 | /// <summary>
|
83 |
| - /// Converts the assignments into a lambda expression, which creates a Dictionary<string,object%gt;. |
| 78 | + /// Converts the assignments into block of assignments |
84 | 79 | /// </summary>
|
85 | 80 | /// <param name="assignments"></param>
|
86 | 81 | /// <returns>A lambda expression representing the assignments.</returns>
|
87 |
| - static LambdaExpression ConvertAssignmentsToDictionaryExpression<TSource>(IReadOnlyDictionary<string, Expression> assignments) |
| 82 | + static LambdaExpression ConvertAssignmentsToBlockExpression<TSource>(IReadOnlyDictionary<string, Expression> assignments) |
88 | 83 | {
|
89 | 84 | var param = Expression.Parameter(typeof(TSource));
|
90 |
| - var inits = new List<ElementInit>(); |
| 85 | + var variableAndAssignmentDic = new Dictionary<ParameterExpression, Expression>(assignments.Count); |
91 | 86 | foreach (var set in assignments)
|
92 | 87 | {
|
93 | 88 | var setter = set.Value;
|
94 | 89 | if (setter is LambdaExpression setterLambda)
|
95 | 90 | setter = setterLambda.Body.Replace(setterLambda.Parameters.First(), param);
|
96 |
| - inits.Add( |
97 |
| - Expression.ElementInit( |
98 |
| - DictionaryAddMethodInfo, |
99 |
| - Expression.Constant(set.Key), |
100 |
| - Expression.Convert(setter, typeof(object)))); |
| 91 | + |
| 92 | + var var = Expression.Variable(typeof(object), set.Key); |
| 93 | + variableAndAssignmentDic[var] = Expression.Assign(var, Expression.Convert(setter, typeof(object))); |
101 | 94 | }
|
102 | 95 |
|
103 |
| - //The ListInit is intentionally "infected" with the lambda parameter (param), in the form of an IIF. |
104 |
| - //The only relevance is to make sure that the ListInit is not evaluated by the PartialEvaluatingExpressionTreeVisitor, |
105 |
| - //which could turn it into a Constant |
106 |
| - var listInit = Expression.ListInit( |
107 |
| - Expression.New( |
108 |
| - DictionaryConstructorInfo, |
109 |
| - Expression.Condition( |
110 |
| - Expression.Equal(param, Expression.Constant(null, typeof(TSource))), |
111 |
| - Expression.Constant(assignments.Count), |
112 |
| - Expression.Constant(assignments.Count))), |
113 |
| - inits); |
114 |
| - |
115 |
| - return Expression.Lambda(listInit, param); |
| 96 | + return Expression.Lambda(Expression.Block(variableAndAssignmentDic.Keys, variableAndAssignmentDic.Values), param); |
116 | 97 | }
|
117 | 98 |
|
118 | 99 | public static Expression PrepareExpression<TSource, TTarget>(Expression sourceExpression, Expression<Func<TSource, TTarget>> expression)
|
@@ -151,7 +132,7 @@ public static Expression PrepareExpressionFromAnonymous<TSource>(Expression sour
|
151 | 132 |
|
152 | 133 | public static Expression PrepareExpression<TSource>(Expression sourceExpression, IReadOnlyDictionary<string, Expression> assignments)
|
153 | 134 | {
|
154 |
| - var lambda = ConvertAssignmentsToDictionaryExpression<TSource>(assignments); |
| 135 | + var lambda = ConvertAssignmentsToBlockExpression<TSource>(assignments); |
155 | 136 |
|
156 | 137 | return Expression.Call(
|
157 | 138 | ReflectionCache.QueryableMethods.SelectDefinition.MakeGenericMethod(typeof(TSource), lambda.Body.Type),
|
|
0 commit comments