@@ -24,6 +24,8 @@ public class ExpressionTranslator : ExpressionVisitor
2424 public Dictionary < object , string > Constants => _constants ?? ( _constants = new Dictionary < object , string > ( ) ) ;
2525 public Dictionary < Type , string > TypeNames => _typeNames ?? ( _typeNames = new Dictionary < Type , string > ( ) ) ;
2626
27+ public bool HasDynamic { get ; private set ; }
28+
2729 public ExpressionTranslator ( ExpressionDefinitions definitions = null )
2830 {
2931 _definitions = definitions ;
@@ -220,7 +222,7 @@ private void WriteLine()
220222 {
221223 _writer . WriteLine ( ) ;
222224
223- var spaceCount = _indentLevel * Tabsize ;
225+ var spaceCount = _indentLevel * Tabsize ;
224226 _writer . Write ( new string ( ' ' , spaceCount ) ) ;
225227 }
226228
@@ -416,8 +418,11 @@ private string Translate(Type type)
416418 return "ushort" ;
417419 if ( type == typeof ( void ) )
418420 return "void" ;
419- if ( typeof ( IDynamicMetaObjectProvider ) . GetTypeInfo ( ) . IsAssignableFrom ( type . GetTypeInfo ( ) ) )
421+ if ( type . IsNotPublic || typeof ( IDynamicMetaObjectProvider ) . GetTypeInfo ( ) . IsAssignableFrom ( type . GetTypeInfo ( ) ) )
422+ {
423+ HasDynamic = true ;
420424 return "dynamic" ;
425+ }
421426
422427 if ( type . IsArray )
423428 {
@@ -490,8 +495,8 @@ private static bool IsInline(Expression node)
490495 switch ( node . NodeType )
491496 {
492497 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 ) ;
495500
496501 case ExpressionType . Block :
497502 case ExpressionType . DebugInfo :
@@ -512,16 +517,16 @@ private Expression VisitMultiline(Expression node, bool shouldReturn)
512517 switch ( node . NodeType )
513518 {
514519 case ExpressionType . Block :
515- return VisitBlock ( ( BlockExpression ) node , shouldReturn ) ;
520+ return VisitBlock ( ( BlockExpression ) node , shouldReturn ) ;
516521
517522 case ExpressionType . Conditional :
518523 return VisitConditional ( ( ConditionalExpression ) node , shouldReturn ) ;
519524
520525 case ExpressionType . Try :
521- return VisitTry ( ( TryExpression ) node , shouldReturn ) ;
526+ return VisitTry ( ( TryExpression ) node , shouldReturn ) ;
522527
523528 case ExpressionType . Switch :
524- return VisitSwitch ( ( SwitchExpression ) node , shouldReturn ) ;
529+ return VisitSwitch ( ( SwitchExpression ) node , shouldReturn ) ;
525530
526531 //case ExpressionType.DebugInfo:
527532 //case ExpressionType.Goto:
@@ -534,12 +539,12 @@ private Expression VisitMultiline(Expression node, bool shouldReturn)
534539 private Expression VisitBody ( Expression node , bool shouldReturn = false )
535540 {
536541 if ( node . NodeType == ExpressionType . Block )
537- return VisitBlock ( ( BlockExpression ) node , shouldReturn ) ;
542+ return VisitBlock ( ( BlockExpression ) node , shouldReturn ) ;
538543
539544 if ( node . NodeType == ExpressionType . Default && node . Type == typeof ( void ) )
540545 return node ;
541546
542- var lines = VisitBlockBody ( new List < Expression > { node } , shouldReturn ) ;
547+ var lines = VisitBlockBody ( new List < Expression > { node } , shouldReturn ) ;
543548 return Expression . Block ( lines ) ;
544549 }
545550
@@ -602,7 +607,7 @@ private Expression VisitBlock(BlockExpression node, bool shouldReturn)
602607 if ( hasDeclaration )
603608 WriteLine ( ) ;
604609
605- var lines = VisitBlockBody ( node . Expressions , shouldReturn && node . Type != typeof ( void ) ) ;
610+ var lines = VisitBlockBody ( node . Expressions , shouldReturn && node . Type != typeof ( void ) ) ;
606611 return Expression . Block ( list , lines ) ;
607612 }
608613
@@ -846,15 +851,15 @@ protected override Expression VisitDynamic(DynamicExpression node)
846851 {
847852 var expr = VisitGroup ( node . Arguments [ 0 ] , ExpressionType . Index ) ;
848853 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 ) ) ;
850855 }
851856 if ( node . Binder is SetIndexBinder )
852857 {
853858 var expr = VisitGroup ( node . Arguments [ 0 ] , ExpressionType . Index ) ;
854859 var args = VisitArguments ( "[" , node . Arguments . Skip ( 1 ) . Take ( node . Arguments . Count - 2 ) . ToList ( ) , Visit , "]" ) ;
855860 Write ( " = " ) ;
856861 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 } ) ) ;
858863 }
859864 if ( node . Binder is DeleteIndexBinder )
860865 {
@@ -935,7 +940,7 @@ protected override ElementInit VisitElementInit(ElementInit node)
935940 if ( node . Arguments . Count == 1 )
936941 {
937942 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 ;
939944 return node . Update ( args ) ;
940945 }
941946 else
@@ -1038,12 +1043,7 @@ private Expression VisitMember(Expression instance, Expression node, MemberInfo
10381043 }
10391044 else
10401045 {
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 ) ;
10471047 return null ;
10481048 }
10491049 }
@@ -1155,7 +1155,7 @@ protected override Expression VisitLambda<T>(Expression<T> node)
11551155 }
11561156 }
11571157
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
11591159 {
11601160 var wrap = true ;
11611161 if ( list . Count == 0 )
@@ -1186,7 +1186,7 @@ protected override Expression VisitLoop(LoopExpression node)
11861186 Expression body ;
11871187 if ( node . Body . NodeType == ExpressionType . Conditional )
11881188 {
1189- var condExpr = ( ConditionalExpression ) node . Body ;
1189+ var condExpr = ( ConditionalExpression ) node . Body ;
11901190
11911191 if ( condExpr . IfFalse is GotoExpression @break && @break . Target == node . BreakLabel )
11921192 {
@@ -1229,7 +1229,7 @@ protected override MemberAssignment VisitMemberAssignment(MemberAssignment node)
12291229
12301230 protected override Expression VisitMemberInit ( MemberInitExpression node )
12311231 {
1232- var @new = ( NewExpression ) Visit ( node . NewExpression ) ;
1232+ var @new = ( NewExpression ) Visit ( node . NewExpression ) ;
12331233 var args = VisitElements ( node . Bindings , VisitMemberBinding ) ;
12341234 return node . Update ( @new , args ) ;
12351235 }
@@ -1250,6 +1250,9 @@ protected override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBind
12501250
12511251 private static Type GetDelegateType ( MethodInfo method )
12521252 {
1253+ if ( method . GetParameters ( ) . Any ( it => it . IsOut || it . ParameterType . IsByRef ) )
1254+ throw new InvalidOperationException ( "Cannot handle non-public method" ) ;
1255+
12531256 if ( method . ReturnType == typeof ( void ) )
12541257 {
12551258 switch ( method . GetParameters ( ) . Length )
@@ -1271,7 +1274,7 @@ private static Type GetDelegateType(MethodInfo method)
12711274 case 14 : return typeof ( Action < , , , , , , , , , , , , , > ) ;
12721275 case 15 : return typeof ( Action < , , , , , , , , , , , , , , > ) ;
12731276 case 16 : return typeof ( Action < , , , , , , , , , , , , , , , > ) ;
1274- default : return typeof ( Delegate ) ;
1277+ default : throw new InvalidOperationException ( "Cannot handle non-public method" ) ;
12751278 }
12761279 }
12771280 else
@@ -1295,7 +1298,7 @@ private static Type GetDelegateType(MethodInfo method)
12951298 case 14 : return typeof ( Func < , , , , , , , , , , , , , , > ) ;
12961299 case 15 : return typeof ( Func < , , , , , , , , , , , , , , , > ) ;
12971300 case 16 : return typeof ( Func < , , , , , , , , , , , , , , , , > ) ;
1298- default : return typeof ( Delegate ) ;
1301+ default : throw new InvalidOperationException ( "Cannot handle non-public method" ) ;
12991302 }
13001303 }
13011304 }
@@ -1315,22 +1318,15 @@ protected override Expression VisitMethodCall(MethodCallExpression node)
13151318 {
13161319 isNotPublic = true ;
13171320 var del = GetDelegateType ( node . Method ) ;
1318- if ( del == typeof ( Delegate ) )
1321+ if ( del . IsGenericTypeDefinition )
13191322 {
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 ( ) ) ;
13331327 }
1328+ var func = node . Method . CreateDelegate ( del ) ;
1329+ Write ( GetConstant ( func , GetVarName ( node . Method . Name ) ) , ".Invoke" ) ;
13341330 }
13351331 else if ( node . Method . GetCustomAttribute < ExtensionAttribute > ( ) != null )
13361332 {
@@ -1370,7 +1366,7 @@ protected override Expression VisitMethodCall(MethodCallExpression node)
13701366 if ( isExtension )
13711367 {
13721368 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 ( ) ;
13741370 return newArgs . SequenceEqual ( node . Arguments ) ? node : node . Update ( obj , newArgs ) ;
13751371 }
13761372 else
@@ -1391,19 +1387,28 @@ protected override Expression VisitNewArray(NewArrayExpression node)
13911387 {
13921388 if ( node . NodeType == ExpressionType . NewArrayBounds )
13931389 {
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 ) ) ;
13951398 var args = VisitArguments ( "[" , node . Expressions , Visit , "]" ) ;
1399+ for ( int i = 1 ; i < arrayCount ; i ++ )
1400+ Write ( "[]" ) ;
13961401 return node . Update ( args ) ;
13971402 }
13981403 else
13991404 {
1400- Write ( "new[]" ) ;
1405+ Write ( "new " , Translate ( node . Type ) ) ;
14011406 var args = VisitElements ( node . Expressions , Visit ) ;
14021407 return node . Update ( args ) ;
14031408 }
14041409 }
14051410
1406- #region _reservedWords
1411+ #region _reservedWords
14071412 private static readonly HashSet < string > ReservedWords = new HashSet < string >
14081413 {
14091414 "abstract" ,
@@ -1494,7 +1499,7 @@ protected override Expression VisitNewArray(NewArrayExpression node)
14941499 "false" ,
14951500 "true" ,
14961501 } ;
1497- #endregion
1502+ #endregion
14981503
14991504 protected override Expression VisitParameter ( ParameterExpression node )
15001505 {
0 commit comments