建置應用程式時,.NET 多平臺應用程式 UI (.NET MAUI) 可以使用稱為 ILLink 的連結器來減少應用程式的整體大小。 ILLink 藉由分析編譯程式所產生的中繼程式代碼來減少大小。 它會移除未使用的方法、屬性、欄位、事件、結構及類別,以產生只包含執行應用程式所需的程式代碼和元件相依性的應用程式。
鏈接器行為
連結器可讓您修剪 .NET MAUI Android 應用程式。 啟用修剪時,連結器會讓元件維持不變,並藉由移除應用程式未使用的類型和成員來減少 SDK 元件的大小。
您可以針對應用程式的每個組建組態設定連結器行為。 根據預設,偵錯版本停用了修剪功能,而發行版本則啟用了修剪功能。
警告
啟用應用程式偵錯組態的連結器可能會妨礙偵錯體驗,因為它可能會移除屬性存取子,讓您檢查物件的狀態。
若要確保已啟用修剪:
在 Visual Studio 的 方案總管 中,以滑鼠右鍵按兩下 .NET MAUI 應用程式專案,然後選取 [屬性]。 然後,流覽至 [ Android > 選項 ] 索引標籤,並確定已針對發行組建組態啟用修剪:
保留程序代碼
當您使用修剪器時,有時會移除您可能以動態方式呼叫的程式代碼,甚至是間接呼叫的程序代碼。 您可以使用 屬性標註 DynamicDependency 成員,指示修剪器保留成員。 這個屬性可用來表示對成員的類型和子集或特定成員的相依性。
重要
BCL 中無法以靜態方式判斷的應用程式所使用的每個成員,都可能會遭到移除。
屬性 DynamicDependency 可以套用至建構函式、欄位和方法:
[DynamicDependency("Helper", "MyType", "MyAssembly")]
static void RunHelper()
{
var helper = Assembly.Load("MyAssembly").GetType("MyType").GetMethod("Helper");
helper.Invoke(null, null);
}
在此範例中 DynamicDependency ,可確保 方法 Helper 會保留。 如果沒有屬性,修剪將會從 MyAssembly 中移除 Helper,或是完全移除 MyAssembly,如果它未在其他地方被引用。
屬性指定要保留的成員,可以透過 string 或 DynamicallyAccessedMembers 屬性來設定。 型別和組件在屬性內容中可能是隱含的,或明確在屬性中指定 (透過 Type,或透過 string 指定型別及組件名稱)。
型別和成員字串會使用不含成員前置詞的 C# 文件註解識別碼字串格式的變體。 成員字串不應包含宣告類型的名稱,而且可能會省略參數來保留指定名稱的所有成員。 下列範例顯示有效的用法:
[DynamicDependency("Method()")]
[DynamicDependency("Method(System,Boolean,System.String)")]
[DynamicDependency("MethodOnDifferentType()", typeof(ContainingType))]
[DynamicDependency("MemberName")]
[DynamicDependency("MemberOnUnreferencedAssembly", "ContainingType", "UnreferencedAssembly")]
[DynamicDependency("MemberName", "Namespace.ContainingType.NestedType", "Assembly")]
// generics
[DynamicDependency("GenericMethodName``1")]
[DynamicDependency("GenericMethod``2(``0,``1)")]
[DynamicDependency("MethodWithGenericParameterTypes(System.Collections.Generic.List{System.String})")]
[DynamicDependency("MethodOnGenericType(`0)", "GenericType`1", "UnreferencedAssembly")]
[DynamicDependency("MethodOnGenericType(`0)", typeof(GenericType<>))]
保留組件
您可以指定應該從修剪程式排除的元件,同時允許修剪其他元件。 當您無法輕易使用 DynamicDependency 屬性,或無法控制正在修剪的程式代碼時,此方法會很有用。
當它修剪所有組件時,您可以藉由在專案檔中設定 TrimmerRootAssembly MSBuild 項目,告訴修剪器略過組件:
<ItemGroup>
<TrimmerRootAssembly Include="MyAssembly" />
</ItemGroup>
注意
設定 .dllTrimmerRootAssembly MSBuild 屬性時,不需要延伸模組。
如果修剪器略過一個組件,則會將其視為 rooted,這表示會保留它及其所有靜態解析的相依性。 您可以將更多 TrimmerRootAssembly MSBuild 屬性新增至 <ItemGroup>,以略過其他元件。
保留元件、類型和成員
您可以將 XML 描述檔傳遞給修剪工具,以指定需要保留的元件、類型和成員。
若要在修剪所有組件時從修剪過程中排除成員,請將專案檔中的 MSBuild 項目設定為定義要排除之成員的 XML 檔案:
<ItemGroup>
<TrimmerRootDescriptor Include="MyRoots.xml" />
</ItemGroup>
XML 檔案接著會使用修剪器 描述元格式 來定義要排除的成員:
<linker>
<assembly fullname="MyAssembly">
<type fullname="MyAssembly.MyClass">
<method name="DynamicallyAccessedMethod" />
</type>
</assembly>
</linker>
在此範例中,XML 檔案會指定應用程式動態存取的方法,該方法已排除在修剪之外。
當元件、類型或成員列在 XML 中時,預設動作會保留,這表示不論修剪器是否認為它是否使用,都會保留在輸出中。
注意
保留標籤的包容性存在模糊不清。 如果您未提供下一層的詳細數據,則會包含所有子系。 如果未列出任何型別的元件,則會保留所有元件的類型和成員。
將組件標示為修剪安全
如果您的專案中有函式庫,或者您是可重複使用函式庫的開發人員,並且您希望裁剪器將您的組件視為可裁剪,您可以通過在組件的項目檔中新增 IsTrimmable MSBuild 屬性,將組件標記為安全裁剪。
<PropertyGroup>
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>
這會將您的元件標示為「可修剪」,並啟用該專案的修剪警告。 「可修剪」表示您的元件與修剪相容,且建置元件時不應有修剪警告。 在精簡的應用程式中使用時,組件中未使用的成員會在最終的輸出結果中被移除。
在 .NET 9+ 中使用 Native AOT 部署時,將 MSBuild 屬性IsAotCompatible設定true為 也會為該true屬性指派值IsTrimmable,並啟用額外的 AOT 分析器建置屬性。 欲了解更多AOT分析器資訊,請參見 AOT相容性分析器。 欲了解更多關於 .NET MAUI 原生 AOT 部署的資訊,請參見 Native AOT 部署。
在項目檔中將 IsTrimmable MSBuild 屬性設定為 true ,會將 AssemblyMetadata 屬性插入元件中:
[assembly: AssemblyMetadata("IsTrimmable", "True")]
或者,您可以將 AssemblyMetadata 屬性新增至您的組件,而不需要將 IsTrimmable MSBuild 屬性新增至組件的專案檔。
注意
如果已為元件設定 IsTrimmable MSBuild 屬性,這會覆寫 AssemblyMetadata("IsTrimmable", "True") 屬性。 這使您可以選擇將元件納入修剪,即使該元件沒有屬性,或者禁用具有屬性的元件修剪。
隱藏分析警告
啟用修剪器時,它會移除無法靜態存取的 IL。 使用反映或其他建立動態相依性模式的應用程式可能會因此中斷。 若要警告這類模式,當將組件標示為修剪安全時,程式庫作者應將 SuppressTrimAnalysisWarnings MSBuild 屬性設定為 false:
<PropertyGroup>
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
</PropertyGroup>
不隱藏精簡分析警告會包括整個應用程式的警告,包含您自己的程式碼、函式庫程式碼和 SDK 程式碼。
顯示詳細的警告
修剪分析最多會針對來自 PackageReference 的每個組件產生一個警告,指出該組件的內部不相容於修剪。 身為程式庫作者,當您將組件標示為修剪安全時,應該藉由將 TrimmerSingleWarn MSBuild 屬性設定為 false 來啟用所有組件的個別警告:
<PropertyGroup>
<TrimmerSingleWarn>false</TrimmerSingleWarn>
</PropertyGroup>
此設定會顯示所有詳細的警告,而不是將它們折疊為每個元件的單一警告。