Azure DevOps构建的Xamarin Android应用出现System.TypeLoadException问题排查
System.TypeLoadException in Azure DevOps-built Android App Bundles Let’s break down what’s happening here and how to fix it—this is a classic case of build configuration mismatches and linker optimizations causing issues specifically with Azure DevOps-built Android App Bundles.
Why Are These Classes Missing?
This error almost always traces back to aggressive assembly trimming/linking or mismatched build dependencies:
- Linker Optimization Overreach: Android’s linker strips out code it judges as "unused" to shrink app size. If your code has indirect dependencies on types like
System.Data.SqlTypes.SqlBinaryorPropertyChangedEventHandler(for example, via JSON serialization ofDataSetobjects), the linker might fail to detect these references and remove them. Local builds usually disable this aggressive trimming in Debug mode, which is why you don’t hit the issue there. - Assembly Version Mismatches: Azure DevOps might be pulling in older, incompatible versions of assemblies like
System.Data(the 2.0.5.0 version noted is a legacy PCL build). Your local/production builds could be using newer, Android-targeted versions that include these required types. - App Bundle Splitting Issues: Android App Bundles split code into feature modules. If critical assemblies get pushed into on-demand modules instead of the base app, clearing storage forces a fresh install where those modules haven’t downloaded yet, triggering the load failure.
Is This Related to Azure DevOps’ App Bundle Builds?
Absolutely—your local/production builds and Azure DevOps builds are using mismatched configurations, which is the root cause:
- Release vs Debug Configurations: Local Debug builds disable linking by default, but Azure DevOps is likely running a Release configuration with
Link All AssembliesorSdk Assemblies Onlyenabled. - Missing Linker Preservation Rules: Your project probably lacks explicit rules telling the linker to keep these critical types, so the Azure DevOps build strips them out accidentally.
- Environment/Dependency Differences: The Azure DevOps agent might have different SDK versions or missing NuGet packages compared to your local machine, leading to incorrect assembly references during the build.
Fixes to Try
Let’s walk through actionable steps to resolve this:
Add Linker Preservation Rules
Create alink.xmlfile in your Android project root (set its build action toAndroidAsset), and explicitly tell the linker to retain the missing types:<linker> <assembly fullname="System.Data"> <type fullname="System.Data.SqlTypes.SqlBinary" preserve="all" /> <type fullname="System.Data.DataSet" preserve="all" /> </assembly> <assembly fullname="System"> <type fullname="System.ComponentModel.PropertyChangedEventHandler" preserve="all" /> </assembly> <assembly fullname="System.Runtime.Serialization"> <type fullname="System.Runtime.Serialization.DataContractAttribute" preserve="all" /> </assembly> </linker>This ensures the linker doesn’t strip these critical types from the final bundle.
Align Build Configurations
- In your Azure DevOps pipeline, confirm the build uses the exact same configuration as your working production builds (check target framework, linker settings, and code optimization flags).
- Avoid adding extra parameters like
/p:AndroidLinkMode=Fullunless you’ve fully tested your linker preservation rules.
Validate NuGet Restores
- Ensure your pipeline includes a NuGet restore step (use the
NuGetCommand@2task) to pull in all required dependencies. - Double-check that you’re using modern, Android-compatible NuGet packages (e.g.,
System.Data.SqlClientinstead of legacySystem.Datareferences).
- Ensure your pipeline includes a NuGet restore step (use the
Check App Bundle Splitting
- If using App Bundles, verify that critical assemblies aren’t being split into on-demand modules. In your project’s Android Options, review the App Bundle configuration to ensure core dependencies stay in the base app package.
Enable Detailed Build Logs
Togglesystem.debug=truein your Azure DevOps pipeline to get verbose build logs. Look for linker output that lists which types/assemblies are being removed—this will help you refine yourlink.xmlrules if needed.
内容的提问来源于stack exchange,提问作者Kes Walker

