@@ -161,11 +161,37 @@ protected override Expression VisitLambda<T>(Expression<T> node)
161
161
protected override Expression VisitNew ( NewExpression node )
162
162
{
163
163
if ( this . TypeMappings . TryGetValue ( node . Type , out Type newType ) )
164
+ {
164
165
return Expression . New ( newType ) ;
166
+ }
167
+ else if ( node . Arguments . Count > 0 && IsAnonymousType ( node . Type ) )
168
+ {
169
+ ParameterInfo [ ] parameters = node . Type . GetConstructors ( ) [ 0 ] . GetParameters ( ) ;
170
+ Dictionary < string , Expression > bindingExpressions = new Dictionary < string , Expression > ( ) ;
171
+
172
+ for ( int i = 0 ; i < parameters . Length ; i ++ )
173
+ bindingExpressions . Add ( parameters [ i ] . Name , this . Visit ( node . Arguments [ i ] ) ) ;
174
+
175
+ return GetMemberInitExpression ( bindingExpressions , node . Type ) ;
176
+ }
165
177
166
178
return base . VisitNew ( node ) ;
167
179
}
168
180
181
+ private static bool IsAnonymousType ( Type type )
182
+ => type . Name . Contains ( "AnonymousType" )
183
+ &&
184
+ (
185
+ Attribute . IsDefined
186
+ (
187
+ type ,
188
+ typeof ( System . Runtime . CompilerServices . CompilerGeneratedAttribute ) ,
189
+ false
190
+ )
191
+ ||
192
+ type . Assembly . IsDynamic
193
+ ) ;
194
+
169
195
protected override Expression VisitMemberInit ( MemberInitExpression node )
170
196
{
171
197
if ( this . TypeMappings . TryGetValue ( node . Type , out Type newType ) )
@@ -193,9 +219,36 @@ protected override Expression VisitMemberInit(MemberInitExpression node)
193
219
)
194
220
) ;
195
221
}
222
+ else if ( IsAnonymousType ( node . Type ) )
223
+ {
224
+ return GetMemberInitExpression
225
+ (
226
+ node . Bindings
227
+ . OfType < MemberAssignment > ( )
228
+ . ToDictionary
229
+ (
230
+ binding => binding . Member . Name ,
231
+ binding => this . Visit ( binding . Expression )
232
+ ) ,
233
+ node . Type
234
+ ) ;
235
+ }
196
236
197
237
return base . VisitMemberInit ( node ) ;
238
+ }
198
239
240
+ private MemberInitExpression GetMemberInitExpression ( Dictionary < string , Expression > bindingExpressions , Type oldType )
241
+ {
242
+ Type newAnonymousType = AnonymousTypeFactory . CreateAnonymousType ( bindingExpressions . ToDictionary ( a => a . Key , a => a . Value . Type ) ) ;
243
+ TypeMappings . AddTypeMapping ( ConfigurationProvider , oldType , newAnonymousType ) ;
244
+
245
+ return Expression . MemberInit
246
+ (
247
+ Expression . New ( newAnonymousType ) ,
248
+ bindingExpressions
249
+ . ToDictionary ( be => be . Key , be => newAnonymousType . GetMember ( be . Key ) [ 0 ] )
250
+ . Select ( member => Expression . Bind ( member . Value , bindingExpressions [ member . Key ] ) )
251
+ ) ;
199
252
}
200
253
201
254
private MemberInitExpression GetMemberInit ( MemberBindingGroup memberBindingGroup )
@@ -537,8 +590,10 @@ private bool GenericTypeDefinitionsAreEquivalent(Type typeSource, Type typeDesti
537
590
protected void FindDestinationFullName ( Type typeSource , Type typeDestination , string sourceFullName , List < PropertyMapInfo > propertyMapInfoList )
538
591
{
539
592
const string period = "." ;
540
-
541
- if ( typeSource == typeDestination )
593
+ bool BothTypesAreAnonymous ( )
594
+ => IsAnonymousType ( typeSource ) && IsAnonymousType ( typeDestination ) ;
595
+
596
+ if ( typeSource == typeDestination || BothTypesAreAnonymous ( ) )
542
597
{
543
598
var sourceFullNameArray = sourceFullName . Split ( new [ ] { period [ 0 ] } , StringSplitOptions . RemoveEmptyEntries ) ;
544
599
sourceFullNameArray . Aggregate ( propertyMapInfoList , ( list , next ) =>
0 commit comments