Legacy Migration Guide (.NET Framework → .NET 8)
This document is based on the actual migration experience of InspectionHost (.NET Framework 4.8 → .NET 8), summarizing the migration path, considerations, and common issues.
1. Applicable Projects
| Project | Current Version | Migration Status |
|---|---|---|
| Leyu.InspectionHost | .NET 4.8 → .NET 8 | ✅ Completed (LEY-59) |
| Walton Line1/2/3 | .NET 4.5 / VS 2015 | Not planned |
| ENR_DUC | .NET 4.8 | Not planned |
2. Pre-Migration Assessment Checklist
2.1 Third-Party SDK Compatibility
| Status | SDK | Notes |
|---|---|---|
| ✅ | Delta DIASECS (netcoreapp3.1) | Fully compatible with .NET 8 |
| ⚠️ | KGS Common (.NET 4.5) | Requires .NET 8 compatibility testing |
| ⚠️ | Adlink Motion (Native P/Invoke) | Requires x64 DLL verification |
| ✅ | CommunityToolkit.Mvvm | Native .NET 8 support |
| ✅ | HandyControl / LiveCharts2 | NuGet versions available |
2.2 UI Framework
| From | To | Complexity |
|---|---|---|
| WinForms → WPF | UI rewrite required (High) | Recommended for new projects to use WPF directly |
| WinForms → WinForms (.NET 8) | Only update project format (Low) | Preserves existing UI |
3. .csproj Format Conversion
3.1 Before: Legacy Format (631 lines)
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<LangVersion>7.3</LangVersion>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<!-- One PropertyGroup per Configuration|Platform -->
<!-- Each file manually listed as <Compile>, <EmbeddedResource>, <None> -->
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, ...">
<HintPath>..\Dll\Newtonsoft.Json.dll</HintPath>
</Reference>
</Project>
3.2 After: SDK-style Format (38 lines)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<Nullable>disable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.*" />
<PackageReference Include="HandyControl" Version="3.5.1" />
</ItemGroup>
</Project>
3.3 Key Differences
| Aspect | .NET Framework | .NET 8 SDK-style |
|---|---|---|
| File enumeration | Manual <Compile> for each file | Auto globbing (*.cs) |
| Dependencies | <Reference> + HintPath | <PackageReference> NuGet |
| Platform config | Separate for each Config|Platform | Single <TargetFramework> |
| Output path | Manual <OutputPath> | Automatic (bin/Release/net8.0-windows/) |
4. Dependency Management Migration
4.1 NuGet Package Upgrades
| Old (DLL Reference) | New (NuGet) |
|---|---|
Newtonsoft.Json 6.0.0 (local DLL) | <PackageReference Include="Newtonsoft.Json" Version="13.*" /> |
M2Mqtt.Net 4.3.0 (local DLL) | Evaluate alternative packages (MQTTnet) |
System.Data.SQLite (local DLL) | <PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.*" /> |
4.2 Native DLL Handling
Unmanaged DLLs remain as <None> + CopyToOutputDirectory:
<!-- Managed DLL reference -->
<ItemGroup>
<Reference Include="DIASECS">
<HintPath>..\..\lib\DIASECS.dll</HintPath>
</Reference>
</ItemGroup>
<!-- Unmanaged Native DLL (no Reference needed) -->
<ItemGroup>
<None Include="..\..\lib\hasp_net_core.dll" CopyToOutputDirectory="PreserveNewest" />
<None Include="..\..\lib\hasp_windows_x64_24160.dll" CopyToOutputDirectory="PreserveNewest" />
<!-- Preserve subdirectory structure -->
<None Include="..\..\lib\cpsrt\win\x64\cpsrt.dll"
CopyToOutputDirectory="PreserveNewest"
Link="cpsrt\win\x64\cpsrt.dll" />
</ItemGroup>
The Link attribute preserves the subdirectory structure of Native DLLs.
5. MVVM Modernization
5.1 Before: Manual INotifyPropertyChanged
public class ViewModel : INotifyPropertyChanged
{
private string _status;
public string Status
{
get => _status;
set
{
if (_status != value)
{
_status = value;
OnPropertyChanged(nameof(Status));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
5.2 After: Source Generator
public partial class ViewModel : ObservableObject
{
[ObservableProperty]
private string _status;
// 自動產生 Status property + PropertyChanged 通知
}
Code volume reduced by ~70%.
6. DI Integration
6.1 Before: No DI (Manual Instantiation or ServiceLocator)
var service = new SecsService(); // 直接 new
6.2 After: Microsoft.Extensions.DependencyInjection
var services = new ServiceCollection();
// Mock/Real 切換
if (useRealSecs)
services.AddSingleton<ISecsHostService, SecsHostService>();
else
services.AddSingleton<ISecsHostService, MockSecsHostService>();
services.AddSingleton<MainViewModel>();
var provider = services.BuildServiceProvider();
var mainWindow = provider.GetRequiredService<MainWindow>();
mainWindow.DataContext = provider.GetRequiredService<MainViewModel>();
7. Nullable Reference Types
Recommended to disable during the initial migration phase to avoid a large number of warnings:
<Nullable>disable</Nullable>
Gradually enable and fix later.
8. Async Patterns
8.1 Before: Synchronous Blocking
public void Connect()
{
_driver.Init();
_driver.Start(); // 阻塞 UI Thread
}
8.2 After: Task-based Async
public Task ConnectAsync(string eqIp, string eqPort)
{
return Task.Run(() =>
{
_driver.Init();
_driver.Start();
});
}
9. Migration Step Checklist
- Create a new SDK-style .csproj (
<Project Sdk="Microsoft.NET.Sdk">) - Set TargetFramework:
net8.0-windows(add-windowsfor WPF/WinForms) - Migrate dependencies:
<Reference>→<PackageReference> - Handle Native DLLs:
<None ... CopyToOutputDirectory="PreserveNewest" /> - Configure Nullable:
disableinitially - Update MVVM: Manual Property →
[ObservableProperty] - Introduce DI:
Microsoft.Extensions.DependencyInjection - Async conversion: Synchronous blocking →
async/await - Test SDK compatibility: Verify third-party SDKs one by one
- Build verification:
dotnet build+dotnet run
10. InspectionHost Migration Experience
| Item | Result |
|---|---|
| Delta DIASECS SDK | ✅ netcoreapp3.1 DLL fully compatible with .NET 8 |
| HASP / CodeMeter Licensing | ✅ Native DLL works correctly via <None> + Link |
| WinForms → WPF | ✅ Full rewrite (with HandyControl Dark Theme) |
| DI Introduction | ✅ Mock/Real SECS dual-mode switching |
| CommunityToolkit.Mvvm | ✅ Source Generator works correctly |
| .csproj | 631 lines → 38 lines |
Document Version: v1.0 | Created: 2026-03-16 | Related Issue: GST-173