3
3
using System . Collections . ObjectModel ;
4
4
using System . Linq ;
5
5
using System . Linq . Expressions ;
6
- using System . Reflection ;
7
6
using NHibernate . Linq . Visitors ;
8
- using NHibernate . Util ;
9
7
10
8
namespace NHibernate . Linq
11
9
{
12
- public abstract class Assignments
13
- {
14
- protected static readonly ConstructorInfo DictionaryConstructorInfo = typeof ( Dictionary < string , object > ) . GetConstructor ( new [ ] { typeof ( int ) } ) ;
15
- protected static readonly MethodInfo DictionaryAddMethodInfo = ReflectHelper . GetMethod < Dictionary < string , object > > ( d => d . Add ( null , null ) ) ;
16
- }
17
-
18
10
/// <summary>
19
11
/// Class to hold assignments used in updates and inserts.
20
12
/// </summary>
21
13
/// <typeparam name="TSource">The type of the entity source of the insert or to update.</typeparam>
22
14
/// <typeparam name="TTarget">The type of the entity to insert or to update.</typeparam>
23
- public class Assignments < TSource , TTarget > : Assignments
15
+ public class Assignments < TSource , TTarget >
24
16
{
25
17
private readonly List < Assignment > _sets = new List < Assignment > ( ) ;
26
18
19
+ internal IReadOnlyCollection < Assignment > List => _sets ;
20
+
27
21
/// <summary>
28
22
/// Sets the specified property.
29
23
/// </summary>
@@ -64,40 +58,6 @@ private static MemberExpression GetMemberExpression<TProp>(Expression<Func<TTarg
64
58
return member ;
65
59
}
66
60
67
- /// <summary>
68
- /// Converts the assignments into a lambda expression, which creates a Dictionary<string,object%gt;.
69
- /// </summary>
70
- /// <returns>A lambda expression representing the assignments.</returns>
71
- public LambdaExpression ConvertToDictionaryExpression ( )
72
- {
73
- var param = Expression . Parameter ( typeof ( TSource ) ) ;
74
- var inits = new List < ElementInit > ( ) ;
75
- foreach ( var set in _sets )
76
- {
77
- var setter = set . Expression ;
78
- if ( setter is LambdaExpression setterLambda )
79
- {
80
- setter = setterLambda . Body . Replace ( setterLambda . Parameters . First ( ) , param ) ;
81
- }
82
- inits . Add ( Expression . ElementInit ( DictionaryAddMethodInfo , Expression . Constant ( set . PropertyPath ) ,
83
- Expression . Convert ( setter , typeof ( object ) ) ) ) ;
84
- }
85
-
86
- //The ListInit is intentionally "infected" with the lambda parameter (param), in the form of an IIF.
87
- //The only relevance is to make sure that the ListInit is not evaluated by the PartialEvaluatingExpressionTreeVisitor,
88
- //which could turn it into a Constant
89
- var listInit = Expression . ListInit (
90
- Expression . New (
91
- DictionaryConstructorInfo ,
92
- Expression . Condition (
93
- Expression . Equal ( param , Expression . Constant ( null , typeof ( TSource ) ) ) ,
94
- Expression . Constant ( _sets . Count ) ,
95
- Expression . Constant ( _sets . Count ) ) ) ,
96
- inits ) ;
97
-
98
- return Expression . Lambda ( listInit , param ) ;
99
- }
100
-
101
61
/// <summary>
102
62
/// Converts a members initialization expression to assignments. Unset members are ignored and left untouched.
103
63
/// </summary>
@@ -107,40 +67,42 @@ public static Assignments<TSource, TTarget> FromExpression(Expression<Func<TSour
107
67
{
108
68
if ( expression == null )
109
69
throw new ArgumentNullException ( nameof ( expression ) ) ;
110
- var instance = new Assignments < TSource , TTarget > ( ) ;
111
70
var memberInitExpression = expression . Body as MemberInitExpression ??
112
- throw new ArgumentException ( "The expression must be member initialization, e.g. x => new Dog { Name = x.Name, Age = x.Age + 5 }" ) ;
113
-
114
- AddSetsFromBindings ( memberInitExpression . Bindings , instance , "" , expression . Parameters ) ;
71
+ throw new ArgumentException ( "The expression must be member initialization, e.g. x => new Dog { Name = x.Name, Age = x.Age + 5 }" ) ;
115
72
73
+ var instance = new Assignments < TSource , TTarget > ( ) ;
74
+ instance . AddSetsFromBindings ( memberInitExpression . Bindings , "" , expression . Parameters ) ;
116
75
return instance ;
117
76
}
118
77
119
- private static void AddSetsFromBindings ( IEnumerable < MemberBinding > bindings , Assignments < TSource , TTarget > instance , string path , ReadOnlyCollection < ParameterExpression > parameters )
78
+ private void AddSetsFromBindings ( IEnumerable < MemberBinding > bindings , string path , ReadOnlyCollection < ParameterExpression > parameters )
120
79
{
121
- foreach ( var binding in bindings )
80
+ foreach ( var node in bindings )
122
81
{
123
- if ( binding . BindingType == MemberBindingType . Assignment ) // {Property="Value"}
124
- {
125
- AddSetsFromAssignment ( ( MemberAssignment ) binding , instance , path + "." + binding . Member . Name , parameters ) ;
126
- }
127
- else if ( binding . BindingType == MemberBindingType . MemberBinding ) // {Property={SubProperty="Value}}
82
+ switch ( node . BindingType )
128
83
{
129
- AddSetsFromBindings ( ( ( MemberMemberBinding ) binding ) . Bindings , instance , path + "." + binding . Member . Name , parameters ) ;
84
+ case MemberBindingType . Assignment :
85
+ AddSetsFromAssignment ( ( MemberAssignment ) node , path + "." + node . Member . Name , parameters ) ;
86
+ break ;
87
+ case MemberBindingType . MemberBinding :
88
+ AddSetsFromBindings ( ( ( MemberMemberBinding ) node ) . Bindings , path + "." + node . Member . Name , parameters ) ;
89
+ break ;
90
+ default :
91
+ throw new InvalidOperationException ( $ "{ node . BindingType } is not supported") ;
130
92
}
131
93
}
132
94
}
133
95
134
- private static void AddSetsFromAssignment ( MemberAssignment assignment , Assignments < TSource , TTarget > instance , string path , ReadOnlyCollection < ParameterExpression > parameters )
96
+ private void AddSetsFromAssignment ( MemberAssignment assignment , string path , ReadOnlyCollection < ParameterExpression > parameters )
135
97
{
136
98
// {Property=new Instance{SubProperty="Value"}}
137
99
if ( assignment . Expression is MemberInitExpression memberInit )
138
100
{
139
- AddSetsFromBindings ( memberInit . Bindings , instance , path , parameters ) ;
101
+ AddSetsFromBindings ( memberInit . Bindings , path , parameters ) ;
140
102
}
141
103
else
142
104
{
143
- instance . _sets . Add ( new Assignment ( path . Substring ( 1 ) , Expression . Lambda ( assignment . Expression , parameters ) ) ) ;
105
+ _sets . Add ( new Assignment ( path . Substring ( 1 ) , Expression . Lambda ( assignment . Expression , parameters ) ) ) ;
144
106
}
145
107
}
146
108
}
0 commit comments