diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 36eabbbab..7178b6e50 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.Ast } else if (type != null && type.IsCompilerGenerated()) { if (type.Name.StartsWith("", StringComparison.Ordinal)) return true; - if (type.Name.StartsWith("<>", StringComparison.Ordinal) && type.Name.Contains("AnonymousType")) + if (type.IsAnonymousType()) return true; } FieldDefinition field = member as FieldDefinition; @@ -885,12 +885,13 @@ namespace ICSharpCode.Decompiler.Ast return astField; } - public static IEnumerable MakeParameters(IEnumerable paramCol) + public static IEnumerable MakeParameters(IEnumerable paramCol, bool isLambda = false) { foreach(ParameterDefinition paramDef in paramCol) { ParameterDeclaration astParam = new ParameterDeclaration(); astParam.AddAnnotation(paramDef); - astParam.Type = ConvertType(paramDef.ParameterType, paramDef); + if (!(isLambda && paramDef.ParameterType.ContainsAnonymousType())) + astParam.Type = ConvertType(paramDef.ParameterType, paramDef); astParam.Name = paramDef.Name; if (paramDef.ParameterType is ByReferenceType) { diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs index eacc1c9c3..3c0f773fb 100644 --- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs @@ -91,7 +91,12 @@ namespace ICSharpCode.Decompiler.Ast Statement insertionPoint = astBlock.Statements.FirstOrDefault(); foreach (ILVariable v in localVariablesToDefine) { - var newVarDecl = new VariableDeclarationStatement(AstBuilder.ConvertType(v.Type), v.Name); + AstType type; + if (v.Type.ContainsAnonymousType()) + type = new SimpleType("var"); + else + type = AstBuilder.ConvertType(v.Type); + var newVarDecl = new VariableDeclarationStatement(type, v.Name); astBlock.Statements.InsertBefore(insertionPoint, newVarDecl); } @@ -603,6 +608,20 @@ namespace ICSharpCode.Decompiler.Ast } } var oce = new Ast.ObjectCreateExpression(); + if (declaringType.IsAnonymousType()) { + MethodDefinition ctor = ((MethodReference)operand).Resolve(); + if (methodDef != null) { + oce.Initializer = new ArrayInitializerExpression(); + for (int i = 0; i < args.Count; i++) { + oce.Initializer.Elements.Add( + new NamedArgumentExpression { + Identifier = ctor.Parameters[i].Name, + Expression = args[i] + }); + } + } + return oce; + } oce.Type = AstBuilder.ConvertType(declaringType); oce.Arguments.AddRange(args); return oce.WithAnnotation(operand); @@ -911,6 +930,8 @@ namespace ICSharpCode.Decompiler.Ast GenericInstanceMethod g = cecilMethod as GenericInstanceMethod; if (g == null) return null; + if (g.GenericArguments.Any(ta => ta.ContainsAnonymousType())) + return null; return g.GenericArguments.Select(t => AstBuilder.ConvertType(t)); } diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs index 0d584c3f4..14e429d05 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs @@ -119,7 +119,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms // Create AnonymousMethodExpression and prepare parameters AnonymousMethodExpression ame = new AnonymousMethodExpression(); - ame.Parameters.AddRange(AstBuilder.MakeParameters(method.Parameters)); + ame.Parameters.AddRange(AstBuilder.MakeParameters(method.Parameters, isLambda: true)); ame.HasParameterList = true; // rename variables so that they don't conflict with the parameters: diff --git a/ICSharpCode.Decompiler/CecilExtensions.cs b/ICSharpCode.Decompiler/CecilExtensions.cs index df7a9b0b6..8b31a2701 100644 --- a/ICSharpCode.Decompiler/CecilExtensions.cs +++ b/ICSharpCode.Decompiler/CecilExtensions.cs @@ -204,5 +204,35 @@ namespace ICSharpCode.Decompiler return true; return IsCompilerGeneratedOrIsInCompilerGeneratedClass(member.DeclaringType); } + + public static bool IsAnonymousType(this TypeReference type) + { + if (type == null) + return false; + if (string.IsNullOrEmpty(type.Namespace) && type.Name.StartsWith("<>", StringComparison.Ordinal) && type.Name.Contains("AnonymousType")) { + TypeDefinition td = type.Resolve(); + return td != null && td.IsCompilerGenerated(); + } + return false; + } + + public static bool ContainsAnonymousType(this TypeReference type) + { + GenericInstanceType git = type as GenericInstanceType; + if (git != null) { + if (IsAnonymousType(git)) + return true; + for (int i = 0; i < git.GenericArguments.Count; i++) { + if (git.GenericArguments[i].ContainsAnonymousType()) + return true; + } + return false; + } + TypeSpecification typeSpec = type as TypeSpecification; + if (typeSpec != null) + return typeSpec.ElementType.ContainsAnonymousType(); + else + return false; + } } }