diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index eca3b0d89..3d371c484 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -1146,6 +1146,11 @@ namespace ICSharpCode.Decompiler.CSharp return methodDecl; } + internal static bool IsWindowsFormsInitializeComponentMethod(IMethod method) + { + return method.ReturnType.Kind == TypeKind.Void && method.Name == "InitializeComponent" && method.DeclaringTypeDefinition.GetNonInterfaceBaseTypes().Any(t => t.FullName == "System.Windows.Forms.Control"); + } + void DecompileBody(MethodDefinition methodDefinition, IMethod method, EntityDeclaration entityDecl, DecompileRun decompileRun, ITypeResolveContext decompilationContext) { try { @@ -1165,7 +1170,15 @@ namespace ICSharpCode.Decompiler.CSharp } } - var context = new ILTransformContext(function, specializingTypeSystem, settings) { + var localSettings = settings.Clone(); + if (IsWindowsFormsInitializeComponentMethod(method)) { + localSettings.UseImplicitMethodGroupConversion = false; + localSettings.UsingDeclarations = false; + localSettings.FullyQualifyAmbiguousTypeNames = true; + localSettings.AlwaysCastTargetsOfExplicitInterfaceImplementationCalls = true; + } + + var context = new ILTransformContext(function, specializingTypeSystem, localSettings) { CancellationToken = CancellationToken, DecompileRun = decompileRun }; @@ -1176,15 +1189,15 @@ namespace ICSharpCode.Decompiler.CSharp // When decompiling definitions only, we can cancel decompilation of all steps // after yield and async detection, because only those are needed to properly set // IsAsync/IsIterator flags on ILFunction. - if (!settings.DecompileMemberBodies && transform is AsyncAwaitDecompiler) + if (!localSettings.DecompileMemberBodies && transform is AsyncAwaitDecompiler) break; } var body = BlockStatement.Null; // Generate C# AST only if bodies should be displayed. - if (settings.DecompileMemberBodies) { + if (localSettings.DecompileMemberBodies) { AddDefinesForConditionalAttributes(function, decompileRun, decompilationContext); - var statementBuilder = new StatementBuilder(specializingTypeSystem, decompilationContext, function, settings, CancellationToken); + var statementBuilder = new StatementBuilder(specializingTypeSystem, decompilationContext, function, localSettings, CancellationToken); body = statementBuilder.ConvertAsBlock(function.Body); Comment prev = null; diff --git a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs index cfa35d37c..bf2cd40c0 100644 --- a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs @@ -309,7 +309,8 @@ namespace ICSharpCode.Decompiler.CSharp typeArgumentList = ((MemberReferenceExpression)targetExpr).TypeArguments; // HACK : convert this.Dispose() to ((IDisposable)this).Dispose(), if Dispose is an explicitly implemented interface method. - if (method.IsExplicitInterfaceImplementation && target.Expression is ThisReferenceExpression) { + // settings.AlwaysCastTargetsOfExplicitInterfaceImplementationCalls == true is used in Windows Forms' InitializeComponent methods. + if (method.IsExplicitInterfaceImplementation && (target.Expression is ThisReferenceExpression || settings.AlwaysCastTargetsOfExplicitInterfaceImplementationCalls)) { var castExpression = new CastExpression(expressionBuilder.ConvertType(method.ImplementedInterfaceMembers[0].DeclaringType), target.Expression); methodName = method.ImplementedInterfaceMembers[0].Name; targetExpr = new MemberReferenceExpression(castExpression, methodName); diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs index 005312f22..595e4b497 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs @@ -174,7 +174,25 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms context.Pop(); } } - + + public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration) + { + if (methodDeclaration.GetSymbol() is IMethod method && CSharpDecompiler.IsWindowsFormsInitializeComponentMethod(method)) { + var previousContext = context.Peek(); + var currentContext = new CSharpTypeResolveContext(previousContext.CurrentAssembly); + context.Push(currentContext); + try { + astBuilder = CreateAstBuilder(currentContext); + base.VisitMethodDeclaration(methodDeclaration); + } finally { + astBuilder = CreateAstBuilder(previousContext); + context.Pop(); + } + } else { + base.VisitMethodDeclaration(methodDeclaration); + } + } + public override void VisitSimpleType(SimpleType simpleType) { TypeResolveResult rr; diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs index 192fba76b..f0a285d84 100644 --- a/ICSharpCode.Decompiler/DecompilerSettings.cs +++ b/ICSharpCode.Decompiler/DecompilerSettings.cs @@ -383,6 +383,24 @@ namespace ICSharpCode.Decompiler } } + bool alwaysCastTargetsOfExplicitInterfaceImplementationCalls = false; + + /// + /// Gets/Sets whether to always cast targets to explicitly implemented methods. + /// true: ((ISupportInitialize)pictureBox1).BeginInit(); + /// false: pictureBox1.BeginInit(); + /// default: false + /// + public bool AlwaysCastTargetsOfExplicitInterfaceImplementationCalls { + get { return alwaysCastTargetsOfExplicitInterfaceImplementationCalls; } + set { + if (alwaysCastTargetsOfExplicitInterfaceImplementationCalls != value) { + alwaysCastTargetsOfExplicitInterfaceImplementationCalls = value; + OnPropertyChanged(); + } + } + } + bool fullyQualifyAmbiguousTypeNames = true; public bool FullyQualifyAmbiguousTypeNames {