@@ -16,7 +16,6 @@ public static class ExpressionBuilder
1616 {
1717 public static readonly MethodInfo ObjectToString = typeof ( object ) . GetMethod ( nameof ( object . ToString ) ) ;
1818 private static readonly MethodInfo DisposeMethod = typeof ( IDisposable ) . GetMethod ( nameof ( IDisposable . Dispose ) ) ;
19- public static readonly Expression False = Constant ( false , typeof ( bool ) ) ;
2019 public static readonly Expression True = Constant ( true , typeof ( bool ) ) ;
2120 public static readonly Expression Null = Constant ( null , typeof ( object ) ) ;
2221 public static readonly Expression Empty = Empty ( ) ;
@@ -34,6 +33,12 @@ public static class ExpressionBuilder
3433 private static readonly MethodInfo CheckContextMethod = typeof ( ResolutionContext ) . GetStaticMethod ( nameof ( ResolutionContext . CheckContext ) ) ;
3534 private static readonly MethodInfo ContextMapMethod = typeof ( ResolutionContext ) . GetInstanceMethod ( nameof ( ResolutionContext . MapInternal ) ) ;
3635 private static readonly MethodInfo ArrayEmptyMethod = typeof ( Array ) . GetStaticMethod ( nameof ( Array . Empty ) ) ;
36+ private static readonly ParameterExpression Disposable = Variable ( typeof ( IDisposable ) , "disposableEnumerator" ) ;
37+ private static readonly ParameterExpression [ ] DisposableArray = new [ ] { Disposable } ;
38+ private static readonly Expression DisposeCall = IfNullElse ( Disposable , Empty , Expression . Call ( Disposable , DisposeMethod ) ) ;
39+ private static readonly ParameterExpression Index = Variable ( typeof ( int ) , "sourceArrayIndex" ) ;
40+ private static readonly BinaryExpression ResetIndex = Assign ( Index , Zero ) ;
41+ private static readonly UnaryExpression IncrementIndex = PostIncrementAssign ( Index ) ;
3742
3843 public static Expression MapExpression ( this IGlobalConfiguration configurationProvider , ProfileMap profileMap , TypePair typePair , Expression sourceParameter ,
3944 MemberMap propertyMap = null , Expression destinationParameter = null )
@@ -47,7 +52,7 @@ public static Expression MapExpression(this IGlobalConfiguration configurationPr
4752 hasTypeConverter = typeMap . HasTypeConverter ;
4853 if ( ! typeMap . HasDerivedTypesToInclude )
4954 {
50- typeMap . Seal ( configurationProvider ) ;
55+ configurationProvider . Seal ( typeMap ) ;
5156 mapExpression = typeMap . MapExpression ? . ConvertReplaceParameters ( sourceParameter , destinationParameter ) ;
5257 }
5358 }
@@ -263,36 +268,34 @@ public static Expression ForEach(ParameterExpression loopVar, Expression collect
263268 static Expression ForEachArrayItem ( ParameterExpression loopVar , Expression array , Expression loopContent )
264269 {
265270 var breakLabel = Label ( "LoopBreak" ) ;
266- var index = Variable ( typeof ( int ) , "sourceArrayIndex" ) ;
267- var loop = Block ( new [ ] { index , loopVar } ,
268- Assign ( index , Zero ) ,
271+ var loop = Block ( new [ ] { Index , loopVar } ,
272+ ResetIndex ,
269273 Loop (
270274 IfThenElse (
271- LessThan ( index , ArrayLength ( array ) ) ,
272- Block ( Assign ( loopVar , ArrayAccess ( array , index ) ) , loopContent , PostIncrementAssign ( index ) ) ,
275+ LessThan ( Index , ArrayLength ( array ) ) ,
276+ Block ( Assign ( loopVar , ArrayAccess ( array , Index ) ) , loopContent , IncrementIndex ) ,
273277 Break ( breakLabel )
274278 ) ,
275279 breakLabel ) ) ;
276280 return loop ;
277281 }
278- static Expression Using ( Expression disposable , Expression body )
282+ static Expression Using ( Expression target , Expression body )
279283 {
280- Expression disposeCall ;
281- if ( typeof ( IDisposable ) . IsAssignableFrom ( disposable . Type ) )
284+ Expression finallyDispose ;
285+ if ( typeof ( IDisposable ) . IsAssignableFrom ( target . Type ) )
282286 {
283- disposeCall = Expression . Call ( disposable , DisposeMethod ) ;
287+ finallyDispose = Expression . Call ( target , DisposeMethod ) ;
284288 }
285289 else
286290 {
287- if ( disposable . Type . IsValueType )
291+ if ( target . Type . IsValueType )
288292 {
289293 return body ;
290294 }
291- var disposableVariable = Variable ( typeof ( IDisposable ) , "disposableVariable" ) ;
292- var assignDisposable = Assign ( disposableVariable , TypeAs ( disposable , typeof ( IDisposable ) ) ) ;
293- disposeCall = Block ( new [ ] { disposableVariable } , assignDisposable , IfNullElse ( disposableVariable , Empty , Expression . Call ( disposableVariable , DisposeMethod ) ) ) ;
295+ var assignDisposable = Assign ( Disposable , TypeAs ( target , typeof ( IDisposable ) ) ) ;
296+ finallyDispose = Block ( DisposableArray , assignDisposable , DisposeCall ) ;
294297 }
295- return TryFinally ( body , disposeCall ) ;
298+ return TryFinally ( body , finallyDispose ) ;
296299 }
297300 }
298301 // Expression.Property(string) is inefficient because it does a case insensitive match
@@ -325,9 +328,9 @@ public static Expression NullCheck(this Expression expression, Type destinationT
325328 {
326329 return expression ;
327330 }
328- var returnType = ( destinationType != null && destinationType != expression . Type && Nullable . GetUnderlyingType ( destinationType ) == expression . Type ) ?
331+ var returnType = ( destinationType != null && destinationType != expression . Type && Nullable . GetUnderlyingType ( destinationType ) == expression . Type ) ?
329332 destinationType : expression . Type ;
330- var defaultReturn = defaultValue ? . Type == returnType ? defaultValue : Default ( returnType ) ;
333+ var defaultReturn = ( defaultValue is { NodeType : ExpressionType . Default } && defaultValue . Type == returnType ) ? defaultValue : Default ( returnType ) ;
331334 ParameterExpression [ ] variables = null ;
332335 var name = parameter . Name ;
333336 int index = 0 ;
@@ -351,9 +354,9 @@ static Expression UpdateTarget(Expression sourceExpression, Expression newTarget
351354 sourceExpression switch
352355 {
353356 MemberExpression memberExpression => memberExpression . Update ( newTarget ) ,
354- MethodCallExpression { Method : { IsStatic : true } , Arguments : var args } methodCall when args [ 0 ] != newTarget =>
355- methodCall . Update ( null , new [ ] { newTarget } . Concat ( args . Skip ( 1 ) ) ) ,
356- MethodCallExpression { Method : { IsStatic : false } } methodCall => methodCall . Update ( newTarget , methodCall . Arguments ) ,
357+ MethodCallExpression { Method . IsStatic : true , Arguments : var args } methodCall when args [ 0 ] != newTarget =>
358+ methodCall . Update ( null , args . Skip ( 1 ) . Prepend ( newTarget ) ) ,
359+ MethodCallExpression { Method . IsStatic : false } methodCall => methodCall . Update ( newTarget , methodCall . Arguments ) ,
357360 _ => sourceExpression ,
358361 } ;
359362 }
0 commit comments