@@ -24,6 +24,8 @@ public class ExpressionTranslator : ExpressionVisitor
24
24
public Dictionary < object , string > Constants => _constants ?? ( _constants = new Dictionary < object , string > ( ) ) ;
25
25
public Dictionary < Type , string > TypeNames => _typeNames ?? ( _typeNames = new Dictionary < Type , string > ( ) ) ;
26
26
27
+ public bool HasDynamic { get ; private set ; }
28
+
27
29
public ExpressionTranslator ( ExpressionDefinitions definitions = null )
28
30
{
29
31
_definitions = definitions ;
@@ -220,7 +222,7 @@ private void WriteLine()
220
222
{
221
223
_writer . WriteLine ( ) ;
222
224
223
- var spaceCount = _indentLevel * Tabsize ;
225
+ var spaceCount = _indentLevel * Tabsize ;
224
226
_writer . Write ( new string ( ' ' , spaceCount ) ) ;
225
227
}
226
228
@@ -416,8 +418,11 @@ private string Translate(Type type)
416
418
return "ushort" ;
417
419
if ( type == typeof ( void ) )
418
420
return "void" ;
419
- if ( typeof ( IDynamicMetaObjectProvider ) . GetTypeInfo ( ) . IsAssignableFrom ( type . GetTypeInfo ( ) ) )
421
+ if ( type . IsNotPublic || typeof ( IDynamicMetaObjectProvider ) . GetTypeInfo ( ) . IsAssignableFrom ( type . GetTypeInfo ( ) ) )
422
+ {
423
+ HasDynamic = true ;
420
424
return "dynamic" ;
425
+ }
421
426
422
427
if ( type . IsArray )
423
428
{
@@ -490,8 +495,8 @@ private static bool IsInline(Expression node)
490
495
switch ( node . NodeType )
491
496
{
492
497
case ExpressionType . Conditional :
493
- var condExpr = ( ConditionalExpression ) node ;
494
- return condExpr . Type != typeof ( void ) && IsInline ( condExpr . IfTrue ) && IsInline ( condExpr . IfFalse ) ;
498
+ var condExpr = ( ConditionalExpression ) node ;
499
+ return condExpr . Type != typeof ( void ) && IsInline ( condExpr . IfTrue ) && IsInline ( condExpr . IfFalse ) ;
495
500
496
501
case ExpressionType . Block :
497
502
case ExpressionType . DebugInfo :
@@ -512,16 +517,16 @@ private Expression VisitMultiline(Expression node, bool shouldReturn)
512
517
switch ( node . NodeType )
513
518
{
514
519
case ExpressionType . Block :
515
- return VisitBlock ( ( BlockExpression ) node , shouldReturn ) ;
520
+ return VisitBlock ( ( BlockExpression ) node , shouldReturn ) ;
516
521
517
522
case ExpressionType . Conditional :
518
523
return VisitConditional ( ( ConditionalExpression ) node , shouldReturn ) ;
519
524
520
525
case ExpressionType . Try :
521
- return VisitTry ( ( TryExpression ) node , shouldReturn ) ;
526
+ return VisitTry ( ( TryExpression ) node , shouldReturn ) ;
522
527
523
528
case ExpressionType . Switch :
524
- return VisitSwitch ( ( SwitchExpression ) node , shouldReturn ) ;
529
+ return VisitSwitch ( ( SwitchExpression ) node , shouldReturn ) ;
525
530
526
531
//case ExpressionType.DebugInfo:
527
532
//case ExpressionType.Goto:
@@ -534,12 +539,12 @@ private Expression VisitMultiline(Expression node, bool shouldReturn)
534
539
private Expression VisitBody ( Expression node , bool shouldReturn = false )
535
540
{
536
541
if ( node . NodeType == ExpressionType . Block )
537
- return VisitBlock ( ( BlockExpression ) node , shouldReturn ) ;
542
+ return VisitBlock ( ( BlockExpression ) node , shouldReturn ) ;
538
543
539
544
if ( node . NodeType == ExpressionType . Default && node . Type == typeof ( void ) )
540
545
return node ;
541
546
542
- var lines = VisitBlockBody ( new List < Expression > { node } , shouldReturn ) ;
547
+ var lines = VisitBlockBody ( new List < Expression > { node } , shouldReturn ) ;
543
548
return Expression . Block ( lines ) ;
544
549
}
545
550
@@ -602,7 +607,7 @@ private Expression VisitBlock(BlockExpression node, bool shouldReturn)
602
607
if ( hasDeclaration )
603
608
WriteLine ( ) ;
604
609
605
- var lines = VisitBlockBody ( node . Expressions , shouldReturn && node . Type != typeof ( void ) ) ;
610
+ var lines = VisitBlockBody ( node . Expressions , shouldReturn && node . Type != typeof ( void ) ) ;
606
611
return Expression . Block ( list , lines ) ;
607
612
}
608
613
@@ -846,15 +851,15 @@ protected override Expression VisitDynamic(DynamicExpression node)
846
851
{
847
852
var expr = VisitGroup ( node . Arguments [ 0 ] , ExpressionType . Index ) ;
848
853
var args = VisitArguments ( "[" , node . Arguments . Skip ( 1 ) . ToList ( ) , Visit , "]" ) ;
849
- return Update ( node , new [ ] { expr } . Concat ( args ) ) ;
854
+ return Update ( node , new [ ] { expr } . Concat ( args ) ) ;
850
855
}
851
856
if ( node . Binder is SetIndexBinder )
852
857
{
853
858
var expr = VisitGroup ( node . Arguments [ 0 ] , ExpressionType . Index ) ;
854
859
var args = VisitArguments ( "[" , node . Arguments . Skip ( 1 ) . Take ( node . Arguments . Count - 2 ) . ToList ( ) , Visit , "]" ) ;
855
860
Write ( " = " ) ;
856
861
var value = VisitGroup ( node . Arguments [ node . Arguments . Count - 1 ] , ExpressionType . Assign ) ;
857
- return Update ( node , new [ ] { expr } . Concat ( args ) . Concat ( new [ ] { value } ) ) ;
862
+ return Update ( node , new [ ] { expr } . Concat ( args ) . Concat ( new [ ] { value } ) ) ;
858
863
}
859
864
if ( node . Binder is DeleteIndexBinder )
860
865
{
@@ -935,7 +940,7 @@ protected override ElementInit VisitElementInit(ElementInit node)
935
940
if ( node . Arguments . Count == 1 )
936
941
{
937
942
var arg = Visit ( node . Arguments [ 0 ] ) ;
938
- var args = arg != node . Arguments [ 0 ] ? new [ ] { arg } . AsEnumerable ( ) : node . Arguments ;
943
+ var args = arg != node . Arguments [ 0 ] ? new [ ] { arg } . AsEnumerable ( ) : node . Arguments ;
939
944
return node . Update ( args ) ;
940
945
}
941
946
else
@@ -1038,12 +1043,7 @@ private Expression VisitMember(Expression instance, Expression node, MemberInfo
1038
1043
}
1039
1044
else
1040
1045
{
1041
- if ( member is PropertyInfo p && p . GetIndexParameters ( ) . Length == 0 && ( member . DeclaringType . IsNotPublic || p . GetGetMethod ( ) == null ) )
1042
- Write ( GetConstant ( p . GetValue ( null ) , member . Name ) ) ;
1043
- else if ( member is FieldInfo f && ( member . DeclaringType . IsNotPublic || ! f . IsPublic ) )
1044
- Write ( GetConstant ( f . GetValue ( null ) , member . Name ) ) ;
1045
- else
1046
- Write ( Translate ( member . DeclaringType ) , "." , member . Name ) ;
1046
+ Write ( Translate ( member . DeclaringType ) , "." , member . Name ) ;
1047
1047
return null ;
1048
1048
}
1049
1049
}
@@ -1155,7 +1155,7 @@ protected override Expression VisitLambda<T>(Expression<T> node)
1155
1155
}
1156
1156
}
1157
1157
1158
- private IList < T > VisitElements < T > ( IList < T > list , Func < T , T > func ) where T : class
1158
+ private IList < T > VisitElements < T > ( IList < T > list , Func < T , T > func ) where T : class
1159
1159
{
1160
1160
var wrap = true ;
1161
1161
if ( list . Count == 0 )
@@ -1186,7 +1186,7 @@ protected override Expression VisitLoop(LoopExpression node)
1186
1186
Expression body ;
1187
1187
if ( node . Body . NodeType == ExpressionType . Conditional )
1188
1188
{
1189
- var condExpr = ( ConditionalExpression ) node . Body ;
1189
+ var condExpr = ( ConditionalExpression ) node . Body ;
1190
1190
1191
1191
if ( condExpr . IfFalse is GotoExpression @break && @break . Target == node . BreakLabel )
1192
1192
{
@@ -1229,7 +1229,7 @@ protected override MemberAssignment VisitMemberAssignment(MemberAssignment node)
1229
1229
1230
1230
protected override Expression VisitMemberInit ( MemberInitExpression node )
1231
1231
{
1232
- var @new = ( NewExpression ) Visit ( node . NewExpression ) ;
1232
+ var @new = ( NewExpression ) Visit ( node . NewExpression ) ;
1233
1233
var args = VisitElements ( node . Bindings , VisitMemberBinding ) ;
1234
1234
return node . Update ( @new , args ) ;
1235
1235
}
@@ -1250,6 +1250,9 @@ protected override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBind
1250
1250
1251
1251
private static Type GetDelegateType ( MethodInfo method )
1252
1252
{
1253
+ if ( method . GetParameters ( ) . Any ( it => it . IsOut || it . ParameterType . IsByRef ) )
1254
+ throw new InvalidOperationException ( "Cannot handle non-public method" ) ;
1255
+
1253
1256
if ( method . ReturnType == typeof ( void ) )
1254
1257
{
1255
1258
switch ( method . GetParameters ( ) . Length )
@@ -1271,7 +1274,7 @@ private static Type GetDelegateType(MethodInfo method)
1271
1274
case 14 : return typeof ( Action < , , , , , , , , , , , , , > ) ;
1272
1275
case 15 : return typeof ( Action < , , , , , , , , , , , , , , > ) ;
1273
1276
case 16 : return typeof ( Action < , , , , , , , , , , , , , , , > ) ;
1274
- default : return typeof ( Delegate ) ;
1277
+ default : throw new InvalidOperationException ( "Cannot handle non-public method" ) ;
1275
1278
}
1276
1279
}
1277
1280
else
@@ -1295,7 +1298,7 @@ private static Type GetDelegateType(MethodInfo method)
1295
1298
case 14 : return typeof ( Func < , , , , , , , , , , , , , , > ) ;
1296
1299
case 15 : return typeof ( Func < , , , , , , , , , , , , , , , > ) ;
1297
1300
case 16 : return typeof ( Func < , , , , , , , , , , , , , , , , > ) ;
1298
- default : return typeof ( Delegate ) ;
1301
+ default : throw new InvalidOperationException ( "Cannot handle non-public method" ) ;
1299
1302
}
1300
1303
}
1301
1304
}
@@ -1315,22 +1318,15 @@ protected override Expression VisitMethodCall(MethodCallExpression node)
1315
1318
{
1316
1319
isNotPublic = true ;
1317
1320
var del = GetDelegateType ( node . Method ) ;
1318
- if ( del == typeof ( Delegate ) )
1321
+ if ( del . IsGenericTypeDefinition )
1319
1322
{
1320
- Write ( "(" , Translate ( node . Method . ReturnType ) , ")" , GetConstant ( del , GetVarName ( node . Method . Name ) ) , ".DynamicInvoke" ) ;
1321
- }
1322
- else
1323
- {
1324
- if ( del . IsGenericTypeDefinition )
1325
- {
1326
- var types = node . Method . GetParameters ( ) . Select ( it => it . ParameterType ) ;
1327
- if ( node . Method . ReturnType != typeof ( void ) )
1328
- types = types . Concat ( new [ ] { node . Method . ReturnType } ) ;
1329
- del = del . MakeGenericType ( types . ToArray ( ) ) ;
1330
- }
1331
- var func = node . Method . CreateDelegate ( del ) ;
1332
- Write ( GetConstant ( func , GetVarName ( node . Method . Name ) ) , ".Invoke" ) ;
1323
+ var types = node . Method . GetParameters ( ) . Select ( it => it . ParameterType ) ;
1324
+ if ( node . Method . ReturnType != typeof ( void ) )
1325
+ types = types . Concat ( new [ ] { node . Method . ReturnType } ) ;
1326
+ del = del . MakeGenericType ( types . ToArray ( ) ) ;
1333
1327
}
1328
+ var func = node . Method . CreateDelegate ( del ) ;
1329
+ Write ( GetConstant ( func , GetVarName ( node . Method . Name ) ) , ".Invoke" ) ;
1334
1330
}
1335
1331
else if ( node . Method . GetCustomAttribute < ExtensionAttribute > ( ) != null )
1336
1332
{
@@ -1370,7 +1366,7 @@ protected override Expression VisitMethodCall(MethodCallExpression node)
1370
1366
if ( isExtension )
1371
1367
{
1372
1368
var args = VisitArguments ( "(" , node . Arguments . Skip ( 1 ) . ToList ( ) , Visit , ")" , prefix : prefix . Skip ( 1 ) . ToList ( ) ) ;
1373
- var newArgs = new [ ] { arg0 } . Concat ( args ) . ToList ( ) ;
1369
+ var newArgs = new [ ] { arg0 } . Concat ( args ) . ToList ( ) ;
1374
1370
return newArgs . SequenceEqual ( node . Arguments ) ? node : node . Update ( obj , newArgs ) ;
1375
1371
}
1376
1372
else
@@ -1391,19 +1387,28 @@ protected override Expression VisitNewArray(NewArrayExpression node)
1391
1387
{
1392
1388
if ( node . NodeType == ExpressionType . NewArrayBounds )
1393
1389
{
1394
- Write ( "new " , Translate ( node . Type . GetElementType ( ) ) ) ;
1390
+ var elemType = node . Type . GetElementType ( ) ;
1391
+ var arrayCount = 1 ;
1392
+ while ( elemType . IsArray )
1393
+ {
1394
+ elemType = elemType . GetElementType ( ) ;
1395
+ arrayCount ++ ;
1396
+ }
1397
+ Write ( "new " , Translate ( elemType ) ) ;
1395
1398
var args = VisitArguments ( "[" , node . Expressions , Visit , "]" ) ;
1399
+ for ( int i = 1 ; i < arrayCount ; i ++ )
1400
+ Write ( "[]" ) ;
1396
1401
return node . Update ( args ) ;
1397
1402
}
1398
1403
else
1399
1404
{
1400
- Write ( "new[]" ) ;
1405
+ Write ( "new " , Translate ( node . Type ) ) ;
1401
1406
var args = VisitElements ( node . Expressions , Visit ) ;
1402
1407
return node . Update ( args ) ;
1403
1408
}
1404
1409
}
1405
1410
1406
- #region _reservedWords
1411
+ #region _reservedWords
1407
1412
private static readonly HashSet < string > ReservedWords = new HashSet < string >
1408
1413
{
1409
1414
"abstract" ,
@@ -1494,7 +1499,7 @@ protected override Expression VisitNewArray(NewArrayExpression node)
1494
1499
"false" ,
1495
1500
"true" ,
1496
1501
} ;
1497
- #endregion
1502
+ #endregion
1498
1503
1499
1504
protected override Expression VisitParameter ( ParameterExpression node )
1500
1505
{
0 commit comments