Browse Source

Centralize MEF export lookup in AppComposition.TryGetExport

Eleven call sites each wrapped AppComposition.Current.GetExport<T>() in a
try/catch that returned null, to survive design-time previews and minimal
test hosts where the composition host isn't up. Replace those copies with
one AppComposition.TryGetExport<T>()/TryGetExports<T>() and inline it at
every site, deleting the per-class wrappers.

The shared helper does not blanket-swallow: host absence is checked
explicitly (the static field, not the throwing Current), and the built-in
TryGetExport(out) reports a missing export as false. So an export that is
present but genuinely broken now surfaces its activation error instead of
being silently turned into null.

Assisted-by: Claude:claude-opus-4-8:Claude Code
pull/3755/head
Siegfried Pammer 4 weeks ago
parent
commit
38c9fc6afa
  1. 19
      ILSpy/AppEnv/AppComposition.cs
  2. 19
      ILSpy/AssemblyTree/AssemblyTreeModel.cs
  3. 9
      ILSpy/Commands/CompareContextMenuEntry.cs
  4. 25
      ILSpy/Docking/DockWorkspace.cs
  5. 33
      ILSpy/Languages/CSharpLanguage.cs
  6. 16
      ILSpy/Languages/ILAstLanguage.cs
  7. 65
      ILSpy/TextView/DecompilerTabPageModel.cs
  8. 14
      ILSpy/Themes/DocumentSwitcherDropdownBehavior.cs
  9. 14
      ILSpy/Themes/MultiRowTabStripBehavior.cs
  10. 9
      ILSpy/Themes/PreviewTabContextMenuBehavior.cs
  11. 9
      ILSpy/Themes/PreviewTabFreezeButtonBehavior.cs
  12. 18
      ILSpy/ViewModels/ContentTabPage.cs
  13. 14
      ILSpy/ViewModels/DebugStepsPaneModel.cs

19
ILSpy/AppEnv/AppComposition.cs

@ -18,8 +18,10 @@ @@ -18,8 +18,10 @@
using System;
using System.Collections.Generic;
using System.Composition;
using System.Composition.Hosting;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
@ -45,6 +47,23 @@ namespace ILSpy.AppEnv @@ -45,6 +47,23 @@ namespace ILSpy.AppEnv
public static CompositionHost Current
=> current ?? throw new InvalidOperationException("Composition host is not yet initialized.");
/// <summary>
/// Resolves a single MEF export, or returns <see langword="null"/> when the composition host
/// isn't initialized yet (design-time previewer, headless pre-boot) or no such export exists.
/// Unlike a blanket try/catch this does NOT swallow composition/activation errors: host
/// absence is checked explicitly and the built-in <c>TryGetExport</c> reports a missing export
/// as <see langword="false"/>, so a genuinely broken export still surfaces its exception.
/// </summary>
public static T? TryGetExport<T>() where T : class
=> current is { } host && host.TryGetExport(out T? export) ? export : null;
/// <summary>
/// Resolves all MEF exports of <typeparamref name="T"/>, or an empty sequence when the host
/// isn't initialized yet. <see cref="TryGetExport{T}"/> for the single-export case.
/// </summary>
public static IEnumerable<T> TryGetExports<T>() where T : class
=> current?.GetExports<T>() ?? Enumerable.Empty<T>();
public static CompositionHost Initialize()
{
RegisterPluginResolver();

19
ILSpy/AssemblyTree/AssemblyTreeModel.cs

@ -183,7 +183,7 @@ namespace ILSpy.AssemblyTree @@ -183,7 +183,7 @@ namespace ILSpy.AssemblyTree
{
// Open the definition in a fresh carve-out tab instead of replacing the current view
// (e.g. "Decompile to new tab" on a symbol in the code).
TryGetExport<Docking.DockWorkspace>()?.OpenNodeInNewTab(resolved);
AppEnv.AppComposition.TryGetExport<Docking.DockWorkspace>()?.OpenNodeInNewTab(resolved);
}
else
{
@ -194,18 +194,11 @@ namespace ILSpy.AssemblyTree @@ -194,18 +194,11 @@ namespace ILSpy.AssemblyTree
// paints local-reference marks on every match once the new Text lands.
if (e.Source is null)
return;
var dockWorkspace = TryGetExport<Docking.DockWorkspace>();
var dockWorkspace = AppEnv.AppComposition.TryGetExport<Docking.DockWorkspace>();
if (dockWorkspace?.ActiveDecompilerTab is { } decompTab)
decompTab.HighlightedReference = e.Source;
}
static T? TryGetExport<T>() where T : class
{
try
{ return AppEnv.AppComposition.Current.GetExport<T>(); }
catch { return null; }
}
// True while the SelectedItem setter is replacing the collection via Clear()+Add();
// suppresses the selection-changed fan-out until the final state is in place so consumers
// never observe the transient empty/multi mid-replace.
@ -455,7 +448,7 @@ namespace ILSpy.AssemblyTree @@ -455,7 +448,7 @@ namespace ILSpy.AssemblyTree
// and its instance IS the AboutCommand, so we can drive its welcome path directly.
void ShowAboutWelcomePage()
{
var registry = TryGetExport<MainMenuCommandRegistry>();
var registry = AppEnv.AppComposition.TryGetExport<MainMenuCommandRegistry>();
var export = registry?.Commands
.FirstOrDefault(c => c.Metadata.Header == nameof(ICSharpCode.ILSpy.Properties.Resources._About))
?.CreateExport();
@ -1050,7 +1043,7 @@ namespace ILSpy.AssemblyTree @@ -1050,7 +1043,7 @@ namespace ILSpy.AssemblyTree
var removed = new HashSet<LoadedAssembly>(oldItems.OfType<LoadedAssembly>());
if (removed.Count > 0)
{
TryGetExport<Docking.DockWorkspace>()?.PruneHistory(node =>
AppEnv.AppComposition.TryGetExport<Docking.DockWorkspace>()?.PruneHistory(node =>
node.AncestorsAndSelf()
.OfType<AssemblyTreeNode>()
.Any(a => removed.Contains(a.LoadedAssembly)));
@ -1092,7 +1085,7 @@ namespace ILSpy.AssemblyTree @@ -1092,7 +1085,7 @@ namespace ILSpy.AssemblyTree
/// (e.g. the ones <see cref="LoadDependenciesAsync"/> just resolved).
/// </summary>
public void RefreshDecompiledView()
=> TryGetExport<Docking.DockWorkspace>()?.ForceRefreshActiveTab();
=> AppEnv.AppComposition.TryGetExport<Docking.DockWorkspace>()?.ForceRefreshActiveTab();
/// <summary>
/// Resolves every assembly reference of each supplied assembly node through that
@ -1154,7 +1147,7 @@ namespace ILSpy.AssemblyTree @@ -1154,7 +1147,7 @@ namespace ILSpy.AssemblyTree
// SelectedItem setter early-outs, and DockWorkspace.ShowSelectedNode's
// dedup short-circuits — leaving stale decompiled text. Force a fresh
// render. Mirrors WPF's RefreshDecompiledView() call.
TryGetExport<Docking.DockWorkspace>()?.ForceRefreshActiveTab();
AppEnv.AppComposition.TryGetExport<Docking.DockWorkspace>()?.ForceRefreshActiveTab();
}
}
}

9
ILSpy/Commands/CompareContextMenuEntry.cs

@ -51,7 +51,7 @@ namespace ILSpy.Commands @@ -51,7 +51,7 @@ namespace ILSpy.Commands
[AssemblyTreeNode left, AssemblyTreeNode right])
return;
var dockWorkspace = TryGetExport<DockWorkspace>();
var dockWorkspace = AppComposition.TryGetExport<DockWorkspace>();
if (dockWorkspace == null)
return;
var pane = new CompareTabPageModel(left.LoadedAssembly, right.LoadedAssembly);
@ -61,12 +61,5 @@ namespace ILSpy.Commands @@ -61,12 +61,5 @@ namespace ILSpy.Commands
// view is a pair, not a single-node decompile result.
dockWorkspace.OpenNewTab(pane);
}
static T? TryGetExport<T>() where T : class
{
try
{ return AppComposition.Current.GetExport<T>(); }
catch { return null; }
}
}
}

25
ILSpy/Docking/DockWorkspace.cs

@ -673,16 +673,7 @@ namespace ILSpy.Docking @@ -673,16 +673,7 @@ namespace ILSpy.Docking
}
static IEnumerable<Commands.IProtocolHandler> TryGetProtocolHandlers()
{
try
{
return AppEnv.AppComposition.Current.GetExports<Commands.IProtocolHandler>();
}
catch
{
return System.Array.Empty<Commands.IProtocolHandler>();
}
}
=> AppEnv.AppComposition.TryGetExports<Commands.IProtocolHandler>();
// Long-lived decompiler viewmodel — kept alive across metadata interludes so going
// back to text doesn't lose the previous decompile until a fresh one supersedes it.
@ -1133,17 +1124,9 @@ namespace ILSpy.Docking @@ -1133,17 +1124,9 @@ namespace ILSpy.Docking
// code-behind subscribes to FocusRequested and posts the focus shift onto the
// dispatcher so the freshly-active pane has a frame to surface in the layout
// first. Resolving the pane through AppComposition (instead of injecting it)
// keeps the dock-workspace decoupled from the search namespace.
try
{
var search = AppEnv.AppComposition.Current.GetExport<ILSpy.Search.SearchPaneModel>();
search.RequestFocus();
}
catch
{
// Composition isn't available in design-time previews / minimal tests; the
// activation alone is enough to be useful there.
}
// keeps the dock-workspace decoupled from the search namespace. TryGetExport is
// null in design-time previews / minimal tests, where the activation alone suffices.
AppEnv.AppComposition.TryGetExport<ILSpy.Search.SearchPaneModel>()?.RequestFocus();
}
public ContentTabPage OpenNewTab(ContentPageModel content, SharpTreeNode? sourceNode = null)

33
ILSpy/Languages/CSharpLanguage.cs

@ -627,19 +627,10 @@ namespace ILSpy.Languages @@ -627,19 +627,10 @@ namespace ILSpy.Languages
}
static IReadOnlyList<IResourceFileHandler> TryDiscoverHandlers()
{
try
{
return AppEnv.AppComposition.Current.GetExports<IResourceFileHandler>().ToArray();
}
catch
{
// Composition isn't available in tests that bypass the host (e.g. invoking
// DecompileAsProject directly with a self-built LoadedAssembly). Fall back
// to the raw-bytes behaviour from the base class.
return System.Array.Empty<IResourceFileHandler>();
}
}
// Composition isn't available in tests that bypass the host (e.g. invoking
// DecompileAsProject directly with a self-built LoadedAssembly); TryGetExports then
// yields nothing, falling back to the raw-bytes behaviour from the base class.
=> AppEnv.AppComposition.TryGetExports<IResourceFileHandler>().ToArray();
}
static List<EntityHandle> CollectFieldsAndCtors(ITypeDefinition type, bool isStatic)
@ -820,17 +811,11 @@ namespace ILSpy.Languages @@ -820,17 +811,11 @@ namespace ILSpy.Languages
static bool HasReferenceErrors(MetadataFile module)
{
try
{
var atm = AppEnv.AppComposition.Current.GetExport<AssemblyTree.AssemblyTreeModel>();
var loadedAssembly = atm.AssemblyList?.GetAssemblies()
.FirstOrDefault(la => la.GetMetadataFileOrNull() == module);
return loadedAssembly?.LoadedAssemblyReferencesInfo.HasErrors == true;
}
catch
{
return false;
}
// No AssemblyTreeModel without a composition host (tests / minimal hosts) -> no errors.
var atm = AppEnv.AppComposition.TryGetExport<AssemblyTree.AssemblyTreeModel>();
var loadedAssembly = atm?.AssemblyList?.GetAssemblies()
.FirstOrDefault(la => la.GetMetadataFileOrNull() == module);
return loadedAssembly?.LoadedAssemblyReferencesInfo.HasErrors == true;
}
}
}

16
ILSpy/Languages/ILAstLanguage.cs

@ -130,17 +130,6 @@ namespace ILSpy.Languages @@ -130,17 +130,6 @@ namespace ILSpy.Languages
this.transforms = CSharpDecompiler.GetILTransforms();
}
// DockWorkspace is resolved lazily — taking it as an [ImportingConstructor] argument
// creates a composition cycle (DockWorkspace already imports LanguageService, which
// imports the registered Languages). Lazy lookup at decompile time breaks the cycle
// and Costs only one MEF GetExport call per "Show Steps" button click.
DockWorkspace? TryGetDockWorkspace()
{
try
{ return AppComposition.Current.GetExport<DockWorkspace>(); }
catch { return null; }
}
public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options)
{
base.DecompileMethod(method, output, options);
@ -188,8 +177,11 @@ namespace ILSpy.Languages @@ -188,8 +177,11 @@ namespace ILSpy.Languages
OnStepperUpdated();
}
}
// DockWorkspace is resolved lazily here, not via [ImportingConstructor]: it imports
// LanguageService, which imports the registered Languages, so a constructor import would
// form a composition cycle. The lazy lookup costs one MEF resolve per "Show Steps" click.
(output as ISmartTextOutput)?.AddButton(Images.Images.ViewCode, "Show Steps", delegate {
TryGetDockWorkspace()?.ShowToolPane(DebugStepsPaneModel.PaneContentId);
AppComposition.TryGetExport<DockWorkspace>()?.ShowToolPane(DebugStepsPaneModel.PaneContentId);
});
output.WriteLine();
il.WriteTo(output, DebugStepsPaneModel.WritingOptions);

65
ILSpy/TextView/DecompilerTabPageModel.cs

@ -278,14 +278,7 @@ namespace ILSpy.TextView @@ -278,14 +278,7 @@ namespace ILSpy.TextView
// still construct cleanly.
TaskbarProgressService? taskbarProgress;
TaskbarProgressService? TaskbarProgress
=> taskbarProgress ??= TryGetExport<TaskbarProgressService>();
static T? TryGetExport<T>() where T : class
{
try
{ return AppEnv.AppComposition.Current.GetExport<T>(); }
catch { return null; }
}
=> taskbarProgress ??= AppEnv.AppComposition.TryGetExport<TaskbarProgressService>();
public DecompilerTabPageModel()
{
@ -358,16 +351,12 @@ namespace ILSpy.TextView @@ -358,16 +351,12 @@ namespace ILSpy.TextView
{
if (CurrentNode is not { } node)
return;
try
{
var languageService = AppEnv.AppComposition.Current.GetExport<Languages.LanguageService>();
var dockWorkspace = AppEnv.AppComposition.Current.GetExport<Docking.DockWorkspace>();
ILSpy.Commands.SaveCodeHelper.SaveNodeAsync(node, languageService, dockWorkspace).HandleExceptions();
}
catch
{
// Best-effort: no save path available (minimal host).
}
// Best-effort: no save path available without a composition host (minimal/design-time host).
var languageService = AppEnv.AppComposition.TryGetExport<Languages.LanguageService>();
var dockWorkspace = AppEnv.AppComposition.TryGetExport<Docking.DockWorkspace>();
if (languageService is null || dockWorkspace is null)
return;
ILSpy.Commands.SaveCodeHelper.SaveNodeAsync(node, languageService, dockWorkspace).HandleExceptions();
}
// Fire-and-forget wrapper around DecompileAsync that observes the resulting Task.
@ -653,35 +642,23 @@ namespace ILSpy.TextView @@ -653,35 +642,23 @@ namespace ILSpy.TextView
// Pulls the live DecompilerSettings via MEF and returns a clone for this run. Also
// bakes the active LanguageService.CurrentVersion into the clone — without this the
// toolbar's Language-Version dropdown writes-through to LanguageSettings but never
// reaches the decompiler. MEF resolves are wrapped in try/catch so design-time /
// minimal test hosts that bypass composition fall back to default settings rather
// than throwing.
// reaches the decompiler. Resolves go through TryGetExport so design-time / minimal test
// hosts that bypass composition fall back to default settings rather than throwing.
static ICSharpCode.Decompiler.DecompilerSettings? TryGetLiveDecompilerSettings()
{
try
{
var settingsService = AppEnv.AppComposition.Current.GetExport<SettingsService>();
var settings = settingsService.DecompilerSettings.Clone();
ApplyDisplaySettings(settings, settingsService.DisplaySettings);
try
{
var version = AppEnv.AppComposition.Current.GetExport<Languages.LanguageService>().CurrentVersion;
if (Enum.TryParse<ICSharpCode.Decompiler.CSharp.LanguageVersion>(version?.Version, out var languageVersion))
settings.SetLanguageVersion(languageVersion);
else
settings.SetLanguageVersion(ICSharpCode.Decompiler.CSharp.LanguageVersion.Latest);
}
catch
{
// No LanguageService available (non-C# language or minimal host) — leave the
// settings at whatever default the source DecompilerSettings carried.
}
return settings;
}
catch
{
var settingsService = AppEnv.AppComposition.TryGetExport<SettingsService>();
if (settingsService is null)
return null;
}
var settings = settingsService.DecompilerSettings.Clone();
ApplyDisplaySettings(settings, settingsService.DisplaySettings);
// No LanguageService (non-C# language or minimal host) leaves version null, so the
// language version falls back to Latest below.
var version = AppEnv.AppComposition.TryGetExport<Languages.LanguageService>()?.CurrentVersion;
if (Enum.TryParse<ICSharpCode.Decompiler.CSharp.LanguageVersion>(version?.Version, out var languageVersion))
settings.SetLanguageVersion(languageVersion);
else
settings.SetLanguageVersion(ICSharpCode.Decompiler.CSharp.LanguageVersion.Latest);
return settings;
}
/// <summary>

14
ILSpy/Themes/DocumentSwitcherDropdownBehavior.cs

@ -69,7 +69,7 @@ namespace ILSpy.Themes @@ -69,7 +69,7 @@ namespace ILSpy.Themes
if (e.NewValue is not true)
return;
var settings = TryGetSessionSettings();
var settings = AppComposition.TryGetExport<SettingsService>()?.SessionSettings;
if (settings is not null)
{
System.ComponentModel.PropertyChangedEventHandler handler = (_, args) => {
@ -138,7 +138,8 @@ namespace ILSpy.Themes @@ -138,7 +138,8 @@ namespace ILSpy.Themes
DockPanel.SetDock(button, Avalonia.Controls.Dock.Right);
dockPanel.Children.Insert(0, button);
UpdateVisibility(strip, TryGetSessionSettings()?.MultiLineDocumentTabs ?? false);
UpdateVisibility(strip,
AppComposition.TryGetExport<SettingsService>()?.SessionSettings?.MultiLineDocumentTabs ?? false);
}
static void PopulateMenu(DocumentTabStrip strip, ContextMenu menu)
@ -166,14 +167,5 @@ namespace ILSpy.Themes @@ -166,14 +167,5 @@ namespace ILSpy.Themes
static Button? FindButton(DocumentTabStrip strip)
=> strip.GetVisualDescendants().OfType<Button>()
.FirstOrDefault(b => (b.Tag as string) == DropdownTag);
static SettingsService? TryGetSettingsService()
{
try
{ return AppComposition.Current.GetExport<SettingsService>(); }
catch { return null; }
}
static SessionSettings? TryGetSessionSettings() => TryGetSettingsService()?.SessionSettings;
}
}

14
ILSpy/Themes/MultiRowTabStripBehavior.cs

@ -71,7 +71,7 @@ namespace ILSpy.Themes @@ -71,7 +71,7 @@ namespace ILSpy.Themes
strip.AddHandler(InputElement.PointerWheelChangedEvent, OnPointerWheel,
RoutingStrategies.Tunnel);
var settings = TryGetSessionSettings();
var settings = AppComposition.TryGetExport<SettingsService>()?.SessionSettings;
PropertyChangedEventHandler? settingsHandler = null;
if (settings is not null)
{
@ -92,7 +92,7 @@ namespace ILSpy.Themes @@ -92,7 +92,7 @@ namespace ILSpy.Themes
static void OnPointerWheel(object? sender, PointerWheelEventArgs e)
{
var settings = TryGetSessionSettings();
var settings = AppComposition.TryGetExport<SettingsService>()?.SessionSettings;
if (settings is null || e.Delta.Y == 0 || !settings.MouseWheelTogglesTabStripRows)
return;
// Idempotent set: rolling further in the same direction keeps the same mode rather than
@ -125,13 +125,7 @@ namespace ILSpy.Themes @@ -125,13 +125,7 @@ namespace ILSpy.Themes
}
}
static bool CurrentMultiLine() => TryGetSessionSettings()?.MultiLineDocumentTabs ?? false;
static SessionSettings? TryGetSessionSettings()
{
try
{ return AppComposition.Current.GetExport<SettingsService>().SessionSettings; }
catch { return null; }
}
static bool CurrentMultiLine()
=> AppComposition.TryGetExport<SettingsService>()?.SessionSettings?.MultiLineDocumentTabs ?? false;
}
}

9
ILSpy/Themes/PreviewTabContextMenuBehavior.cs

@ -106,7 +106,7 @@ namespace ILSpy.Themes @@ -106,7 +106,7 @@ namespace ILSpy.Themes
Header = "Freeze tab",
IsVisible = tab.IsPreview,
};
freezeItem.Click += (_, _) => TryGetDockWorkspace()?.FreezeCurrentTab();
freezeItem.Click += (_, _) => AppComposition.TryGetExport<DockWorkspace>()?.FreezeCurrentTab();
// Keep the Freeze entry (and its separator) in sync with IsPreview so they hide once the
// tab is frozen (freeze is one-way — there's no matching unfreeze entry).
@ -131,12 +131,5 @@ namespace ILSpy.Themes @@ -131,12 +131,5 @@ namespace ILSpy.Themes
},
};
}
static DockWorkspace? TryGetDockWorkspace()
{
try
{ return AppComposition.Current.GetExport<DockWorkspace>(); }
catch { return null; }
}
}
}

9
ILSpy/Themes/PreviewTabFreezeButtonBehavior.cs

@ -170,7 +170,7 @@ namespace ILSpy.Themes @@ -170,7 +170,7 @@ namespace ILSpy.Themes
Mode = BindingMode.OneWay,
});
freezeButton.Click += (_, _) => TryGetDockWorkspace()?.FreezeCurrentTab();
freezeButton.Click += (_, _) => AppComposition.TryGetExport<DockWorkspace>()?.FreezeCurrentTab();
// Insert a new Auto-sized column right before the last (close) column, bump any
// existing children at or past that index by +1, and dock the freeze button there.
@ -186,12 +186,5 @@ namespace ILSpy.Themes @@ -186,12 +186,5 @@ namespace ILSpy.Themes
Grid.SetColumn(freezeButton, newColIndex);
grid.Children.Add(freezeButton);
}
static DockWorkspace? TryGetDockWorkspace()
{
try
{ return AppComposition.Current.GetExport<DockWorkspace>(); }
catch { return null; }
}
}
}

18
ILSpy/ViewModels/ContentTabPage.cs

@ -119,25 +119,13 @@ namespace ILSpy.ViewModels @@ -119,25 +119,13 @@ namespace ILSpy.ViewModels
// Document tab context-menu commands (bound from the DocumentTabStripItem in App.axaml,
// whose DataContext is this tab). The DockWorkspace owns the dock, so resolve it from the
// composition container rather than threading a reference through every tab creation site.
static DockWorkspace? Workspace()
{
try
{
return ILSpy.AppEnv.AppComposition.Current.GetExport<DockWorkspace>();
}
catch
{
return null;
}
}
[CommunityToolkit.Mvvm.Input.RelayCommand]
private void Close() => Workspace()?.CloseTab(this);
private void Close() => ILSpy.AppEnv.AppComposition.TryGetExport<DockWorkspace>()?.CloseTab(this);
[CommunityToolkit.Mvvm.Input.RelayCommand]
private void CloseAllButThis() => Workspace()?.CloseAllTabsExcept(this);
private void CloseAllButThis() => ILSpy.AppEnv.AppComposition.TryGetExport<DockWorkspace>()?.CloseAllTabsExcept(this);
[CommunityToolkit.Mvvm.Input.RelayCommand]
private void CloseAll() => Workspace()?.CloseAllTabs();
private void CloseAll() => ILSpy.AppEnv.AppComposition.TryGetExport<DockWorkspace>()?.CloseAllTabs();
}
}

14
ILSpy/ViewModels/DebugStepsPaneModel.cs

@ -205,17 +205,9 @@ namespace ILSpy.ViewModels @@ -205,17 +205,9 @@ namespace ILSpy.ViewModels
void RequestRedecompile(int stepLimit, bool isDebug)
{
lastSelectedStep = stepLimit;
DockWorkspace? dock;
try
{
dock = AppComposition.Current.GetExport<DockWorkspace>();
}
catch
{
// Composition unavailable in design-time previews; the gesture is a no-op there.
return;
}
dock.ActiveDecompilerTab?.RestartDecompileWithStepLimit(stepLimit, isDebug);
// Composition unavailable in design-time previews; the gesture is a no-op there.
var dock = AppComposition.TryGetExport<DockWorkspace>();
dock?.ActiveDecompilerTab?.RestartDecompileWithStepLimit(stepLimit, isDebug);
}
}
}

Loading…
Cancel
Save