Collegamento di un'app ANDROID .NET MAUI
Quando compila l'app, l'interfaccia utente dell'app multipiattaforma .NET (.NET MAUI) può usare un linker chiamato ILLink per ridurre le dimensioni complessive dell'app. ILLink riduce le dimensioni analizzando il codice intermedio prodotto dal compilatore. Rimuove metodi, proprietà, campi, eventi, struct e classi inutilizzati per produrre un'app che contiene solo dipendenze di codice e assembly necessarie per eseguire l'app.
Comportamento del linker
Il linker consente di tagliare le app ANDROID .NET MAUI. Quando il taglio è abilitato, il linker lascia invariati gli assembly e riduce le dimensioni degli assembly SDK rimuovendo tipi e membri che l'app non usa.
Il comportamento del linker può essere configurato per ogni configurazione di compilazione dell'app. Per impostazione predefinita, il taglio è disabilitato per le compilazioni di debug e abilitato per le build di versione.
Avviso
L'abilitazione del linker per la configurazione di debug dell'app può ostacolare l'esperienza di debug, perché può rimuovere le funzioni di accesso alle proprietà che consentono di controllare lo stato degli oggetti.
Per assicurarsi che il taglio sia abilitato:
In Visual Studio, in Esplora soluzioni, fare clic con il pulsante destro del mouse sul progetto di app .NET MAUI e scegliere Proprietà. Passare quindi alla > Android e assicurarsi che il taglio sia abilitato per la configurazione della build di versione:
Mantenere il codice
Quando si usa il trimmer, talvolta rimuove il codice che potrebbe essere stato chiamato in modo dinamico, anche indirettamente. È possibile indicare al trimmer di mantenere i membri annotandoli con l'attributo DynamicDependency
. Questo attributo può essere usato per esprimere una dipendenza da un tipo e da un subset di membri o da membri specifici.
Importante
Ogni membro dell'elenco di controllo di gruppo che non può essere determinato in modo statico da usare dall'app è soggetto a essere rimosso.
L'attributo DynamicDependency
può essere applicato a costruttori, campi e metodi:
[DynamicDependency("Helper", "MyType", "MyAssembly")]
static void RunHelper()
{
var helper = Assembly.Load("MyAssembly").GetType("MyType").GetMethod("Helper");
helper.Invoke(null, null);
}
In questo esempio, garantisce DynamicDependency
che il Helper
metodo venga mantenuto. Senza l'attributo, il taglio rimuove Helper
MyAssembly
o rimuove MyAssembly
completamente se non viene fatto riferimento altrove.
L'attributo specifica il membro da mantenere tramite o string
tramite l'attributo DynamicallyAccessedMembers
. Il tipo e l'assembly sono impliciti nel contesto dell'attributo oppure specificati in modo esplicito nell'attributo (da Type
o da string
per il tipo e il nome dell'assembly).
Le stringhe di tipo e membro usano una variante del formato di stringa dell’ID commento della documentazione di C#, senza il prefisso del membro. La stringa del membro non deve includere il nome del tipo dichiarante e può omettere i parametri per mantenere tutti i membri del nome specificato. Gli esempi seguenti mostrano usi validi:
[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<>))]
Mantenere gli assembly
È possibile specificare assembly che devono essere esclusi dal processo di taglio, consentendo al contempo l'eliminazione di altri assembly. Questo approccio può essere utile quando non è possibile usare facilmente l'attributo DynamicDependency
o non controllare il codice da tagliare.
Quando taglia tutti gli assembly, è possibile indicare al trimmer di ignorare un assembly impostando un TrimmerRootAssembly
elemento MSBuild nel file di progetto:
<ItemGroup>
<TrimmerRootAssembly Include="MyAssembly" />
</ItemGroup>
Nota
L'estensione .dll
non è necessaria quando si imposta la TrimmerRootAssembly
proprietà MSBuild.
Se il trimmer ignora un assembly, viene considerato rooted, il che significa che vengono mantenute tutte le relative dipendenze comprensibili in modo statico. È possibile ignorare altri assembly aggiungendo altre TrimmerRootAssembly
proprietà di MSBuild a <ItemGroup>
.
Mantenere assembly, tipi e membri
È possibile passare il trimmer di un file di descrizione XML che specifica quali assembly, tipi e membri devono essere conservati.
Per escludere un membro dal processo di taglio quando si tagliano tutti gli assembly, impostare l'elemento TrimmerRootDescriptor
MSBuild nel file di progetto sul file XML che definisce i membri da escludere:
<ItemGroup>
<TrimmerRootDescriptor Include="MyRoots.xml" />
</ItemGroup>
Il file XML usa quindi il formato del descrittore trimmer per definire i membri da escludere:
<linker>
<assembly fullname="MyAssembly">
<type fullname="MyAssembly.MyClass">
<method name="DynamicallyAccessedMethod" />
</type>
</assembly>
</linker>
In questo esempio, il file XML specifica un metodo accessibile dinamicamente dall'app, escluso dal taglio.
Quando un assembly, un tipo o un membro è elencato nel codice XML, l'azione predefinita è l'archiviazione, il che significa che indipendentemente dal fatto che il trimmer pensi che venga usato o meno, viene mantenuto nell'output.
Nota
I tag di conservazione sono ambiguamente inclusivi. Se non fornisci il livello di dettaglio successivo, includerà tutti gli elementi figlio. Se un assembly è elencato senza alcun tipo, tutti i tipi e i membri dell'assembly verranno mantenuti.
Contrassegnare un assembly come ritaglio sicuro
Se si dispone di una libreria nel progetto o si è uno sviluppatore di una libreria riutilizzabile e si vuole che il trimmer consideri l'assembly come trimmable, è possibile contrassegnare l'assembly come trim safe aggiungendo la IsTrimmable
proprietà MSBuild al file di progetto per l'assembly:
<PropertyGroup>
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>
Questo contrassegna l'assembly come "trimmable" e abilita gli avvisi di taglio per il progetto. Essere "trimmable" significa che l'assembly è considerato compatibile con il taglio e non deve avere avvisi di taglio quando viene compilato l'assembly. Se usato in un'app tagliata, i membri inutilizzati dell'assembly vengono rimossi nell'output finale.
Quando si usa la distribuzione AOT nativa in .NET 9+, impostando la proprietà IsAotCompatible
MSBuild su true
assegna anche un valore di true
alla proprietà IsTrimmable
e abilita proprietà di compilazione aggiuntive dell'analizzatore AOT. Per ulteriori informazioni sugli analizzatori di compatibilità AOT, vedere AOT-compatibility analyzers. Per ulteriori informazioni sulla distribuzione AOT nativa per .NET MAUI, vedere distribuzione AOT nativa per .NET MAUI.
L'impostazione della IsTrimmable
proprietà MSBuild su true
nel file di progetto inserisce l'attributo nell'assembly AssemblyMetadata
:
[assembly: AssemblyMetadata("IsTrimmable", "True")]
In alternativa, è possibile aggiungere l'attributo nell'assembly AssemblyMetadata
senza aver aggiunto la IsTrimmable
proprietà MSBuild al file di progetto per l'assembly.
Nota
Se la IsTrimmable
proprietà MSBuild è impostata per un assembly, viene eseguito l'override dell'attributo AssemblyMetadata("IsTrimmable", "True")
. Ciò consente di acconsentire esplicitamente a un assembly di taglio anche se non dispone dell'attributo o di disabilitare il taglio di un assembly con l'attributo .
Eliminare gli avvisi di analisi
Quando il trimmer è abilitato, rimuove IL che non è raggiungibile in modo statico. Le app che usano reflection o altri modelli che creano dipendenze dinamiche possono essere interrotte di conseguenza. Per avvisare di questi modelli, quando si contrassegna un assembly come tronco sicuro, gli autori della libreria devono impostare la SuppressTrimAnalysisWarnings
proprietà MSBuild su false
:
<PropertyGroup>
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
</PropertyGroup>
La mancata eliminazione degli avvisi di analisi di taglio includerà avvisi sull'intera app, tra cui codice personalizzato, codice della libreria e codice SDK.
Mostra avvisi dettagliati
L'analisi trim genera al massimo un avviso per ogni assembly proveniente da un PackageReference
oggetto , a indicare che gli elementi interni dell'assembly non sono compatibili con il taglio. In qualità di autore della libreria, quando si contrassegna un assembly come ritaglio sicuro, è necessario abilitare singoli avvisi per tutti gli assembly impostando la TrimmerSingleWarn
proprietà MSBuild su false
:
<PropertyGroup>
<TrimmerSingleWarn>false</TrimmerSingleWarn>
</PropertyGroup>
Questa impostazione mostra tutti gli avvisi dettagliati, invece di compressione in un singolo avviso per assembly.