Verknüpfung einer .NET MAUI iOS-App
Bei der Erstellung Ihrer App kann .NET Multi-platform App UI (.NET MAUI) einen Linker namens ILLink verwenden, um die Gesamtgröße der App zu reduzieren. ILLink reduziert die Größe, indem der vom Compiler erzeugte Zwischencode analysiert wird. Es entfernt nicht verwendete Methoden, Eigenschaften, Felder, Ereignisse, Strukturen und Klassen, um eine App zu erstellen, die nur Code und Assembly-Abhängigkeiten enthält, die für die Ausführung der App erforderlich sind.
Linkerverhalten
Der Linker unterstützt drei Modi für .NET MAUI-Apps auf iOS und Mac Catalyst:
- Nicht verknüpfen. Durch die Deaktivierung der Verknüpfung wird sichergestellt, dass die Baugruppen nicht verändert werden.
- Nur SDK-Assemblies verknüpfen. In diesem Modus lässt der Linker Ihre Assemblys unberührt und reduziert die Größe der SDK-Assemblys, indem Typen und Member entfernt werden, die Ihre App nicht verwendet.
- Alle Assemblys verknüpfen. Wenn alle Assemblys verknüpft sind, führt der Linker zusätzliche Optimierungen durch, um Ihre App so klein wie möglich zu machen. Er ändert den Zwischencode für Den Quellcode, der Ihre App möglicherweise unterbrechen kann, wenn Sie Features verwenden, die einen Ansatz verwenden, der von der statischen Analyse des Linkers nicht erkannt werden kann. In diesen Fällen müssen Sie möglicherweise Anpassungen am Quellcode vornehmen, damit Ihre App ordnungsgemäß funktioniert.
Das Linker-Verhalten kann für jede Build-Konfiguration Ihrer App konfiguriert werden.
Warnung
Das Aktivieren des Linkers für die Debug-Konfiguration Ihrer App kann Ihre Debugging-Erfahrung beeinträchtigen, da dadurch möglicherweise Eigenschaftszugriffsfunktionen entfernt werden, die es Ihnen ermöglichen, den Zustand Ihrer Objekte zu überprüfen.
So konfigurieren Sie das Verhalten des Linkers in Visual Studio:
Im Solution Explorer klicken Sie mit der rechten Maustaste auf Ihr .NET MAUI App Projekt und wählen Eigenschaften. Navigieren Sie dann zur Registerkarte iOS > Build und setzen Sie das Dropdown-Menü Linker-Verhalten auf Ihr gewünschtes Linker-Verhalten:
Code beibehalten
Wenn Sie den Trimmer verwenden, entfernt es manchmal Code, den Sie möglicherweise dynamisch aufgerufen haben, sogar indirekt. Sie können den Trimmer anweisen, Mitglieder beizubehalten, indem Sie sie mit dem DynamicDependency
Attribut kommentieren. Dieses Attribut kann verwendet werden, um eine Abhängigkeit entweder von einem Typ und einer Teilmenge von Mitgliedern oder von bestimmten Mitgliedern auszudrücken.
Wichtig
Jedes Mitglied der BCL, bei dem nicht statisch festgestellt werden kann, dass es von der App verwendet wird, muss entfernt werden.
Das Attribut DynamicDependency
kann auf Konstruktoren, Felder und Methoden angewendet werden:
[DynamicDependency("Helper", "MyType", "MyAssembly")]
static void RunHelper()
{
var helper = Assembly.Load("MyAssembly").GetType("MyType").GetMethod("Helper");
helper.Invoke(null, null);
}
In diesem Beispiel sorgt das DynamicDependency
dafür, dass die Methode Helper
beibehalten wird. Ohne das Attribut würde Helper
die Kürzung vollständig entfernt MyAssembly
oder entfernt MyAssembly
, wenn sie nicht an anderer Stelle referenziert wird.
Das Attribut gibt das zu behaltende Mitglied über ein string
oder über das DynamicallyAccessedMembers
-Attribut an. Der Typ und die Assembly sind entweder implizit im Attributkontext oder explizit im Attribut angegeben (durch Type
oder durch string
s für den Typ und den Assemblynamen).
Die Typ- und Member-Zeichenfolgen verwenden eine Variation des Zeichenfolgenformats der Kommentar-ID aus der C#-Dokumentation ohne das Member-Präfix. Die Memberzeichenfolge sollte nicht den Namen des deklarierenden Typs enthalten und kann Parameter weglassen, um alle Member des angegebenen Namens beizubehalten. Die folgenden Beispiele zeigen gültige Verwendungen:
[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<>))]
Beibehalten von Assemblys
Es ist möglich, Assemblys anzugeben, die vom Kürzungsprozess ausgeschlossen werden sollten, während andere Assemblys gekürzt werden können. Dieser Ansatz kann nützlich sein, wenn Sie das DynamicDependency
Attribut nicht einfach verwenden können, oder den Code, der gekürzt wird, nicht steuern.
Wenn alle Assemblys gekürzt werden, können Sie den Trimmer anweisen, eine Assembly zu überspringen, indem Sie ein TrimmerRootAssembly
MSBuild-Element in der Projektdatei festlegen:
<ItemGroup>
<TrimmerRootAssembly Include="MyAssembly" />
</ItemGroup>
Hinweis
Die Erweiterung .dll
ist nicht erforderlich, wenn die Eigenschaft TrimmerRootAssembly
MSBuild eingestellt wird.
Wenn der Trimmer eine Assembly überspringt, wird sie als gewurzelt betrachtet, was bedeutet, dass sie und alle ihre statisch verstandenen Abhängigkeiten beibehalten werden. Sie können zusätzliche Assemblies überspringen, indem Sie weitere TrimmerRootAssembly
MSBuild-Eigenschaften zu <ItemGroup>
hinzufügen.
Beibehalten von Assemblys, Typen und Elementen
Sie können den Trimmer an eine XML-Beschreibungsdatei übergeben, die angibt, welche Assemblys, Typen und Member aufbewahrt werden müssen.
Um ein Element beim Kürzen aller Assemblys auszuschließen, legen Sie das TrimmerRootDescriptor
MSBuild-Element in der Projektdatei auf die XML-Datei fest, die die auszuschließenden Member definiert:
<ItemGroup>
<TrimmerRootDescriptor Include="MyRoots.xml" />
</ItemGroup>
Die XML-Datei verwendet dann das Trimmerdeskriptorformat, um zu definieren, welche Member ausgeschlossen werden sollen:
<linker>
<assembly fullname="MyAssembly">
<type fullname="MyAssembly.MyClass">
<method name="DynamicallyAccessedMethod" />
</type>
</assembly>
</linker>
In diesem Beispiel gibt die XML-Datei eine Methode an, auf die dynamisch von der App zugegriffen wird, die von der Kürzung ausgeschlossen wird.
Wenn eine Assembly, ein Typ oder ein Element im XML-Code aufgeführt ist, wird die Standardaktion beibehalten. Dies bedeutet, dass der Trimmer unabhängig davon, ob er verwendet wird oder nicht, in der Ausgabe beibehalten wird.
Hinweis
Die Erhaltungstags sind mehrdeutig inklusive. Wenn Sie nicht die nächste Detailebene angeben, enthält sie alle untergeordneten Elemente. Wenn eine Assembly ohne Typen aufgeführt ist, werden alle Typen und Member der Assembly beibehalten.
Kennzeichnen einer Assembly als sicher zuschneiden
Wenn Sie über eine Bibliothek in Ihrem Projekt verfügen oder Entwickler einer wiederverwendbaren Bibliothek sind und möchten, dass der Trimmer Die Assembly als trimmbar behandeln kann, können Sie die Assembly als sicher markieren, indem Sie die IsTrimmable
MSBuild-Eigenschaft zur Projektdatei für die Assembly hinzufügen:
<PropertyGroup>
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>
Dadurch wird Ihre Assembly als „kürzbar“ gekennzeichnet, und Kürzungswarnungen werden für dieses Projekt aktiviert. „Kürzbar“ bedeutet, dass Ihre Bibliothek als mit Kürzungen kompatibel gilt und beim Erstellen der Bibliothek keine Kürzungswarnungen enthalten sollte. Wenn die Assembly in einer gekürzten App verwendet wird, werden die nicht verwendeten Member in der finalen Ausgabe gekürzt.
Wenn Sie die MSBuild-Eigenschaft IsTrimmable
in Ihrer Projektdatei auf true
setzen, wird das Attribut AssemblyMetadata
in Ihre Assembly eingefügt:
[assembly: AssemblyMetadata("IsTrimmable", "True")]
Alternativ können Sie das AssemblyMetadata
-Attribut in Ihre Assembly einfügen, ohne die IsTrimmable
MSBuild-Eigenschaft zur Projektdatei für Ihre Baugruppe hinzugefügt zu haben.
Hinweis
Wenn die IsTrimmable
-MSBuild-Eigenschaft für eine Assembly festgelegt ist, überschreibt dies das AssemblyMetadata("IsTrimmable", "True")
-Attribut. Damit können Sie eine Baugruppe für das Trimmen auswählen, auch wenn sie das Attribut nicht hat, oder das Trimmen einer Baugruppe, die das Attribut hat, deaktivieren.
Unterdrücken von Codeanalysewarnungen
Wenn der Trimmer aktiviert ist, entfernt er il, der nicht statisch erreichbar ist. Apps, die Reflexion oder andere Muster verwenden, die die dynamischen Abhängigkeiten erstellen, können durch das Kürzen beschädigt werden. Um solche Muster zu warnen, sollten Bibliotheksautoren beim Markieren einer Assembly als sicher zuschneiden die SuppressTrimAnalysisWarnings
MSBuild-Eigenschaft auf false
Folgendes festlegen:
<PropertyGroup>
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
</PropertyGroup>
Dies schließt Warnungen zur gesamten App ein, einschließlich Ihres eigenen Codes, Bibliothekscodes und Frameworkcodes.
Anzeigen ausführlicher Warnungen
Die Trimm-Analyse erzeugt höchstens eine Warnung für jede Baugruppe, die von einem PackageReference
stammt, was darauf hinweist, dass die Interna der Baugruppe nicht mit dem Trimmen kompatibel sind. Als Bibliotheksautor sollten Sie, wenn Sie eine Assembly als Kürzung sicher markieren, einzelne Warnungen für alle Assemblys aktivieren, indem Sie die TrimmerSingleWarn
MSBuild-Eigenschaft auf false
:
<PropertyGroup>
<TrimmerSingleWarn>false</TrimmerSingleWarn>
</PropertyGroup>
Zeigen Sie alle detaillierten Warnungen an, anstatt sie auf eine einzelne Warnung pro Assembly zu reduzieren.