first commit
This commit is contained in:
+439
@@ -0,0 +1,439 @@
|
||||
# Cross-Platform Abstraction Layer
|
||||
|
||||
<cite>
|
||||
**Referenced Files in This Document**
|
||||
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
|
||||
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
|
||||
- [WPFDispatcher.cs](file://ClassicAssist/WPFDispatcher.cs)
|
||||
- [WPFUIInvoker.cs](file://ClassicAssist/WPFUIInvoker.cs)
|
||||
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
|
||||
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
|
||||
- [Engine.cs (Shared)](file://ClassicAssist.Shared/Engine.cs)
|
||||
- [Engine.cs (WPF)](file://ClassicAssist/Engine.cs)
|
||||
- [Engine.cs (Avalonia)](file://ClassicAssist.Avalonia/Engine.cs)
|
||||
- [Program.cs (Avalonia)](file://ClassicAssist.Avalonia/Program.cs)
|
||||
- [App.axaml.cs (Avalonia)](file://ClassicAssist.Avalonia/App.axaml.cs)
|
||||
- [MessageBoxProvider.cs](file://ClassicAssist.Shared/Misc/MessageBoxProvider.cs)
|
||||
- [AvaloniaMessageBoxProvider.cs](file://ClassicAssist.Avalonia/Misc/AvaloniaMessageBoxProvider.cs)
|
||||
- [WPFMessageBoxProvider.cs](file://ClassicAssist/UI/Misc/WPFMessageBoxProvider.cs)
|
||||
- [NativeMethods.cs](file://ClassicAssist.Shared/Misc/NativeMethods.cs)
|
||||
- [PlatformDetector.cs](file://ClassicAssist.Shared/Engine/PlatformDetector.cs)
|
||||
</cite>
|
||||
|
||||
## Table of Contents
|
||||
1. [Introduction](#introduction)
|
||||
2. [Project Structure](#project-structure)
|
||||
3. [Core Components](#core-components)
|
||||
4. [Architecture Overview](#architecture-overview)
|
||||
5. [Detailed Component Analysis](#detailed-component-analysis)
|
||||
6. [Dependency Analysis](#dependency-analysis)
|
||||
7. [Performance Considerations](#performance-considerations)
|
||||
8. [Troubleshooting Guide](#troubleshooting-guide)
|
||||
9. [Conclusion](#conclusion)
|
||||
10. [Appendices](#appendices)
|
||||
|
||||
## Introduction
|
||||
This document explains the cross-platform abstraction layer that enables ClassicAssist to run on Windows, Linux, and macOS. It focuses on:
|
||||
- The dispatcher interface for thread marshaling
|
||||
- UI invoker patterns for cross-thread UI updates
|
||||
- Platform-specific optimizations
|
||||
- Handling differences in window management, file system access, and native interop calls across platforms
|
||||
- Migration strategies and platform-specific considerations
|
||||
|
||||
The goal is to provide a clear understanding of how shared logic remains platform-agnostic while delegating platform-specific behavior through well-defined interfaces.
|
||||
|
||||
## Project Structure
|
||||
At a high level, the project separates shared logic from platform-specific implementations:
|
||||
- Shared abstractions and core engine live in ClassicAssist.Shared
|
||||
- WPF-based implementation lives in ClassicAssist
|
||||
- Avalonia-based implementation lives in ClassicAssist.Avalonia
|
||||
- Launcher and updater are separate applications with their own UI frameworks
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Shared"
|
||||
S_ID["IDispatcher.cs"]
|
||||
S_UI["IUIInvoker.cs"]
|
||||
S_Eng["Engine.cs (Shared)"]
|
||||
S_MsgProv["MessageBoxProvider.cs"]
|
||||
S_Native["NativeMethods.cs"]
|
||||
S_Platform["PlatformDetector.cs"]
|
||||
end
|
||||
subgraph "WPF"
|
||||
W_Dispatch["WPFDispatcher.cs"]
|
||||
W_UIInv["WPFUIInvoker.cs"]
|
||||
W_Eng["Engine.cs (WPF)"]
|
||||
W_MsgProv["WPFMessageBoxProvider.cs"]
|
||||
end
|
||||
subgraph "Avalonia"
|
||||
A_Dispatch["AvaloniaDispatcher.cs"]
|
||||
A_UIInv["AvaloniaUIInvoker.cs"]
|
||||
A_Eng["Engine.cs (Avalonia)"]
|
||||
A_Program["Program.cs (Avalonia)"]
|
||||
A_App["App.axaml.cs (Avalonia)"]
|
||||
A_MsgProv["AvaloniaMessageBoxProvider.cs"]
|
||||
end
|
||||
S_ID --> W_Dispatch
|
||||
S_ID --> A_Dispatch
|
||||
S_UI --> W_UIInv
|
||||
S_UI --> A_UIInv
|
||||
S_Eng --> W_Eng
|
||||
S_Eng --> A_Eng
|
||||
S_MsgProv --> W_MsgProv
|
||||
S_MsgProv --> A_MsgProv
|
||||
S_Native --> W_Eng
|
||||
S_Native --> A_Eng
|
||||
S_Platform --> W_Eng
|
||||
S_Platform --> A_Eng
|
||||
A_Program --> A_Eng
|
||||
A_App --> A_Eng
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
|
||||
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
|
||||
- [WPFDispatcher.cs](file://ClassicAssist/WPFDispatcher.cs)
|
||||
- [WPFUIInvoker.cs](file://ClassicAssist/WPFUIInvoker.cs)
|
||||
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
|
||||
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
|
||||
- [Engine.cs (Shared)](file://ClassicAssist.Shared/Engine.cs)
|
||||
- [Engine.cs (WPF)](file://ClassicAssist/Engine.cs)
|
||||
- [Engine.cs (Avalonia)](file://ClassicAssist.Avalonia/Engine.cs)
|
||||
- [Program.cs (Avalonia)](file://ClassicAssist.Avalonia/Program.cs)
|
||||
- [App.axaml.cs (Avalonia)](file://ClassicAssist.Avalonia/App.axaml.cs)
|
||||
- [MessageBoxProvider.cs](file://ClassicAssist.Shared/Misc/MessageBoxProvider.cs)
|
||||
- [WPFMessageBoxProvider.cs](file://ClassicAssist/UI/Misc/WPFMessageBoxProvider.cs)
|
||||
- [AvaloniaMessageBoxProvider.cs](file://ClassicAssist.Avalonia/Misc/AvaloniaMessageBoxProvider.cs)
|
||||
- [NativeMethods.cs](file://ClassicAssist.Shared/Misc/NativeMethods.cs)
|
||||
- [PlatformDetector.cs](file://ClassicAssist.Shared/Engine/PlatformDetector.cs)
|
||||
|
||||
**Section sources**
|
||||
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
|
||||
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
|
||||
- [Engine.cs (Shared)](file://ClassicAssist.Shared/Engine.cs)
|
||||
- [Engine.cs (WPF)](file://ClassicAssist/Engine.cs)
|
||||
- [Engine.cs (Avalonia)](file://ClassicAssist.Avalonia/Engine.cs)
|
||||
- [Program.cs (Avalonia)](file://ClassicAssist.Avalonia/Program.cs)
|
||||
- [App.axaml.cs (Avalonia)](file://ClassicAssist.Avalonia/App.axaml.cs)
|
||||
- [MessageBoxProvider.cs](file://ClassicAssist.Shared/Misc/MessageBoxProvider.cs)
|
||||
- [WPFMessageBoxProvider.cs](file://ClassicAssist/UI/Misc/WPFMessageBoxProvider.cs)
|
||||
- [AvaloniaMessageBoxProvider.cs](file://ClassicAssist.Avalonia/Misc/AvaloniaMessageBoxProvider.cs)
|
||||
- [NativeMethods.cs](file://ClassicAssist.Shared/Misc/NativeMethods.cs)
|
||||
- [PlatformDetector.cs](file://ClassicAssist.Shared/Engine/PlatformDetector.cs)
|
||||
|
||||
## Core Components
|
||||
The cross-platform abstraction centers around two primary interfaces:
|
||||
- Dispatcher interface for thread marshaling
|
||||
- UI Invoker interface for cross-thread UI updates
|
||||
|
||||
These interfaces are implemented per platform (WPF and Avalonia), allowing shared code to remain framework-agnostic.
|
||||
|
||||
Key responsibilities:
|
||||
- Marshal work onto the UI thread safely
|
||||
- Provide a consistent API for invoking UI operations from background threads
|
||||
- Abstract away platform-specific threading models and message pumps
|
||||
|
||||
**Section sources**
|
||||
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
|
||||
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
|
||||
- [WPFDispatcher.cs](file://ClassicAssist/WPFDispatcher.cs)
|
||||
- [WPFUIInvoker.cs](file://ClassicAssist/WPFUIInvoker.cs)
|
||||
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
|
||||
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
|
||||
|
||||
## Architecture Overview
|
||||
The architecture uses dependency injection or static initialization to select the correct platform implementation at runtime. Shared components depend only on interfaces, not concrete classes.
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class IDispatcher {
|
||||
+ "Dispatch(action)"
|
||||
+ "BeginInvoke(action)"
|
||||
+ "Invoke(action)"
|
||||
}
|
||||
class IUIInvoker {
|
||||
+ "InvokeOnUiThread(action)"
|
||||
+ "IsOnUIThread()"
|
||||
}
|
||||
class WPFDispatcher
|
||||
class WPFUIInvoker
|
||||
class AvaloniaDispatcher
|
||||
class AvaloniaUIInvoker
|
||||
IDispatcher <|.. WPFDispatcher : "implements"
|
||||
IDispatcher <|.. AvaloniaDispatcher : "implements"
|
||||
IUIInvoker <|.. WPFUIInvoker : "implements"
|
||||
IUIInvoker <|.. AvaloniaUIInvoker : "implements"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
|
||||
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
|
||||
- [WPFDispatcher.cs](file://ClassicAssist/WPFDispatcher.cs)
|
||||
- [WPFUIInvoker.cs](file://ClassicAssist/WPFUIInvoker.cs)
|
||||
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
|
||||
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
|
||||
|
||||
## Detailed Component Analysis
|
||||
|
||||
### Dispatcher Interface and Implementations
|
||||
Purpose:
|
||||
- Provide a unified way to schedule work on the UI thread regardless of the underlying UI framework
|
||||
- Support both synchronous and asynchronous dispatching patterns
|
||||
|
||||
Implementation highlights:
|
||||
- WPFDispatcher bridges to WPF’s dispatcher model
|
||||
- AvaloniaDispatcher bridges to Avalonia’s dispatcher model
|
||||
- Both expose methods to enqueue actions and ensure they execute on the UI thread
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant BG as "Background Thread"
|
||||
participant Shared as "Shared Code"
|
||||
participant Disp as "IDispatcher"
|
||||
participant Impl as "WPFDispatcher / AvaloniaDispatcher"
|
||||
participant UIThread as "UI Thread"
|
||||
BG->>Shared : "Perform long-running task"
|
||||
Shared->>Disp : "BeginInvoke(action)"
|
||||
Disp->>Impl : "Forward call"
|
||||
Impl->>UIThread : "Marshal action"
|
||||
UIThread-->>Impl : "Execute action"
|
||||
Impl-->>Shared : "Return"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
|
||||
- [WPFDispatcher.cs](file://ClassicAssist/WPFDispatcher.cs)
|
||||
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
|
||||
|
||||
**Section sources**
|
||||
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
|
||||
- [WPFDispatcher.cs](file://ClassicAssist/WPFDispatcher.cs)
|
||||
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
|
||||
|
||||
### UI Invoker Interface and Implementations
|
||||
Purpose:
|
||||
- Encapsulate UI framework-specific invocation semantics
|
||||
- Offer IsOnUIThread checks and safe InvokeOnUiThread helpers
|
||||
|
||||
Implementation highlights:
|
||||
- WPFUIInvoker uses WPF’s thread affinity APIs
|
||||
- AvaloniaUIInvoker uses Avalonia’s thread context APIs
|
||||
- Shared code calls IUIInvoker without knowing the underlying framework
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["Start"]) --> Check["Check if currently on UI thread"]
|
||||
Check --> |Yes| ExecuteDirect["Execute UI update directly"]
|
||||
Check --> |No| Enqueue["Enqueue action via dispatcher"]
|
||||
Enqueue --> Wait["Wait for completion if needed"]
|
||||
ExecuteDirect --> End(["End"])
|
||||
Wait --> End
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
|
||||
- [WPFUIInvoker.cs](file://ClassicAssist/WPFUIInvoker.cs)
|
||||
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
|
||||
|
||||
**Section sources**
|
||||
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
|
||||
- [WPFUIInvoker.cs](file://ClassicAssist/WPFUIInvoker.cs)
|
||||
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
|
||||
|
||||
### Engine Initialization and Platform Selection
|
||||
Purpose:
|
||||
- Initialize the correct platform-specific dispatcher and UI invoker
|
||||
- Configure application lifecycle and entry points per platform
|
||||
|
||||
Implementation highlights:
|
||||
- Shared Engine defines common startup logic and configuration
|
||||
- WPF Engine initializes WPF-specific resources and sets up WPFDispatcher/WPFUIInvoker
|
||||
- Avalonia Engine initializes Avalonia-specific resources and sets up AvaloniaDispatcher/AvaloniaUIInvoker
|
||||
- Avalonia Program and App coordinate bootstrapping and DI setup
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant OS as "Operating System"
|
||||
participant Entry as "Program.cs (Avalonia)"
|
||||
participant App as "App.axaml.cs (Avalonia)"
|
||||
participant Eng as "Engine.cs (Avalonia)"
|
||||
participant Disp as "AvaloniaDispatcher"
|
||||
participant UIInv as "AvaloniaUIInvoker"
|
||||
OS->>Entry : "Launch process"
|
||||
Entry->>App : "Initialize Avalonia"
|
||||
App->>Eng : "Create and configure Engine"
|
||||
Eng->>Disp : "Register dispatcher"
|
||||
Eng->>UIInv : "Register UI invoker"
|
||||
Eng-->>App : "Ready"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [Program.cs (Avalonia)](file://ClassicAssist.Avalonia/Program.cs)
|
||||
- [App.axaml.cs (Avalonia)](file://ClassicAssist.Avalonia/App.axaml.cs)
|
||||
- [Engine.cs (Avalonia)](file://ClassicAssist.Avalonia/Engine.cs)
|
||||
- [Engine.cs (WPF)](file://ClassicAssist/Engine.cs)
|
||||
- [Engine.cs (Shared)](file://ClassicAssist.Shared/Engine.cs)
|
||||
|
||||
**Section sources**
|
||||
- [Engine.cs (Shared)](file://ClassicAssist.Shared/Engine.cs)
|
||||
- [Engine.cs (WPF)](file://ClassicAssist/Engine.cs)
|
||||
- [Engine.cs (Avalonia)](file://ClassicAssist.Avalonia/Engine.cs)
|
||||
- [Program.cs (Avalonia)](file://ClassicAssist.Avalonia/Program.cs)
|
||||
- [App.axaml.cs (Avalonia)](file://ClassicAssist.Avalonia/App.axaml.cs)
|
||||
|
||||
### Window Management Abstraction
|
||||
Purpose:
|
||||
- Provide a consistent API for creating, showing, and managing windows across platforms
|
||||
- Hide differences between WPF Window and Avalonia Window lifecycles
|
||||
|
||||
Approach:
|
||||
- Use platform-specific providers registered by each Engine implementation
|
||||
- Expose simple Create/Show/Close operations from shared code
|
||||
|
||||
Considerations:
|
||||
- Ensure UI thread affinity when manipulating window state
|
||||
- Handle platform differences in modal dialogs and owner relationships
|
||||
|
||||
[No sources needed since this section doesn't analyze specific files]
|
||||
|
||||
### File System Access Abstraction
|
||||
Purpose:
|
||||
- Normalize path separators, case sensitivity, and special directories across platforms
|
||||
- Provide helper utilities for reading/writing configuration and data files
|
||||
|
||||
Approach:
|
||||
- Use shared utility functions that adapt to platform specifics
|
||||
- Centralize path resolution and normalization
|
||||
|
||||
Considerations:
|
||||
- Respect user profile locations and sandboxing constraints
|
||||
- Handle permission differences on Linux/macOS vs Windows
|
||||
|
||||
[No sources needed since this section doesn't analyze specific files]
|
||||
|
||||
### Native Interop Calls
|
||||
Purpose:
|
||||
- Provide a single point for platform-specific native calls
|
||||
- Abstract away differences in P/Invoke signatures and availability
|
||||
|
||||
Approach:
|
||||
- Define conditional compilation or runtime detection for available APIs
|
||||
- Wrap native calls behind shared interfaces where possible
|
||||
|
||||
Considerations:
|
||||
- Guard against missing symbols on non-Windows platforms
|
||||
- Prefer managed alternatives when available
|
||||
|
||||
**Section sources**
|
||||
- [NativeMethods.cs](file://ClassicAssist.Shared/Misc/NativeMethods.cs)
|
||||
- [PlatformDetector.cs](file://ClassicAssist.Shared/Engine/PlatformDetector.cs)
|
||||
|
||||
### Message Box Provider Abstraction
|
||||
Purpose:
|
||||
- Standardize user-facing dialog interactions across platforms
|
||||
- Allow shared code to show messages without depending on UI framework details
|
||||
|
||||
Implementation highlights:
|
||||
- MessageBoxProvider defines the shared contract
|
||||
- WPFMessageBoxProvider implements it using WPF dialogs
|
||||
- AvaloniaMessageBoxProvider implements it using Avalonia dialogs
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class MessageBoxProvider {
|
||||
<<interface>>
|
||||
+ "Show(message)"
|
||||
}
|
||||
class WPFMessageBoxProvider
|
||||
class AvaloniaMessageBoxProvider
|
||||
MessageBoxProvider <|.. WPFMessageBoxProvider : "implements"
|
||||
MessageBoxProvider <|.. AvaloniaMessageBoxProvider : "implements"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [MessageBoxProvider.cs](file://ClassicAssist.Shared/Misc/MessageBoxProvider.cs)
|
||||
- [WPFMessageBoxProvider.cs](file://ClassicAssist/UI/Misc/WPFMessageBoxProvider.cs)
|
||||
- [AvaloniaMessageBoxProvider.cs](file://ClassicAssist.Avalonia/Misc/AvaloniaMessageBoxProvider.cs)
|
||||
|
||||
**Section sources**
|
||||
- [MessageBoxProvider.cs](file://ClassicAssist.Shared/Misc/MessageBoxProvider.cs)
|
||||
- [WPFMessageBoxProvider.cs](file://ClassicAssist/UI/Misc/WPFMessageBoxProvider.cs)
|
||||
- [AvaloniaMessageBoxProvider.cs](file://ClassicAssist.Avalonia/Misc/AvaloniaMessageBoxProvider.cs)
|
||||
|
||||
## Dependency Analysis
|
||||
The following diagram shows how shared interfaces are implemented by platform-specific classes and how engines wire them together.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Shared["Shared Interfaces<br/>IDispatcher, IUIInvoker"] --> WPFImpl["WPF Implementations<br/>WPFDispatcher, WPFUIInvoker"]
|
||||
Shared --> AvaloniaImpl["Avalonia Implementations<br/>AvaloniaDispatcher, AvaloniaUIInvoker"]
|
||||
SharedEng["Shared Engine"] --> WPFEng["WPF Engine"]
|
||||
SharedEng --> AvaloniaEng["Avalonia Engine"]
|
||||
WPFEng --> WPFImpl
|
||||
AvaloniaEng --> AvaloniaImpl
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
|
||||
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
|
||||
- [WPFDispatcher.cs](file://ClassicAssist/WPFDispatcher.cs)
|
||||
- [WPFUIInvoker.cs](file://ClassicAssist/WPFUIInvoker.cs)
|
||||
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
|
||||
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
|
||||
- [Engine.cs (Shared)](file://ClassicAssist.Shared/Engine.cs)
|
||||
- [Engine.cs (WPF)](file://ClassicAssist/Engine.cs)
|
||||
- [Engine.cs (Avalonia)](file://ClassicAssist.Avalonia/Engine.cs)
|
||||
|
||||
**Section sources**
|
||||
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
|
||||
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
|
||||
- [WPFDispatcher.cs](file://ClassicAssist/WPFDispatcher.cs)
|
||||
- [WPFUIInvoker.cs](file://ClassicAssist/WPFUIInvoker.cs)
|
||||
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
|
||||
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
|
||||
- [Engine.cs (Shared)](file://ClassicAssist.Shared/Engine.cs)
|
||||
- [Engine.cs (WPF)](file://ClassicAssist/Engine.cs)
|
||||
- [Engine.cs (Avalonia)](file://ClassicAssist.Avalonia/Engine.cs)
|
||||
|
||||
## Performance Considerations
|
||||
- Minimize cross-thread marshals: batch UI updates when possible to reduce dispatcher overhead
|
||||
- Avoid blocking the UI thread: use BeginInvoke-style patterns for long-running tasks
|
||||
- Prefer lightweight invocations: keep actions small and focused to reduce contention
|
||||
- Cache frequently accessed platform info: avoid repeated platform detection calls
|
||||
- Be mindful of memory pressure: avoid capturing large objects in dispatched closures
|
||||
|
||||
[No sources needed since this section provides general guidance]
|
||||
|
||||
## Troubleshooting Guide
|
||||
Common issues and resolutions:
|
||||
- Cross-thread operation exceptions: ensure all UI updates go through IUIInvoker.InvokeOnUiThread
|
||||
- Deadlocks on UI thread: avoid calling synchronous Invoke from the UI thread; prefer asynchronous patterns
|
||||
- Missing platform features: guard native calls with platform detection and fallbacks
|
||||
- Dialog visibility problems: verify that dialogs are shown on the correct UI thread and have proper owners
|
||||
|
||||
**Section sources**
|
||||
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
|
||||
- [WPFUIInvoker.cs](file://ClassicAssist/WPFUIInvoker.cs)
|
||||
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
|
||||
- [PlatformDetector.cs](file://ClassicAssist.Shared/Engine/PlatformDetector.cs)
|
||||
|
||||
## Conclusion
|
||||
The cross-platform abstraction layer cleanly separates shared logic from platform-specific concerns using well-defined interfaces for dispatching and UI invocation. By centralizing platform selection in the Engine implementations and providing consistent APIs for window management, file system access, and native interop, ClassicAssist achieves robust support across Windows, Linux, and macOS. Following the migration strategies and performance guidelines outlined here will help maintain stability and portability as the codebase evolves.
|
||||
|
||||
[No sources needed since this section summarizes without analyzing specific files]
|
||||
|
||||
## Appendices
|
||||
|
||||
### Migration Strategies
|
||||
- Introduce new platform-specific feature:
|
||||
- Add an interface method to the relevant shared interface if necessary
|
||||
- Implement the method in WPF and Avalonia providers
|
||||
- Update Engines to register the new provider
|
||||
- Replace direct UI framework calls:
|
||||
- Refactor to use IUIInvoker and IDispatcher
|
||||
- Remove direct references to WPF/Avalonia types from shared code
|
||||
- Handle native interop:
|
||||
- Wrap calls in shared utilities with platform guards
|
||||
- Provide no-op or alternative implementations for unsupported platforms
|
||||
|
||||
[No sources needed since this section doesn't analyze specific files]
|
||||
Reference in New Issue
Block a user