Поделиться через


Связывание приложения .NET MAUI Mac Catalyst

При создании приложения пользовательский интерфейс многоплатформенного приложения .NET (.NET MAUI) может использовать компоновщик, вызывающийся ILLink для уменьшения общего размера приложения. ILLink уменьшает размер, анализируя промежуточный код, созданный компилятором. Он удаляет неиспользуемые методы, свойства, поля, события, структуры и классы для создания приложения, содержащего только зависимости кода и сборки, необходимые для запуска приложения.

Поведение компоновщика

Компоновщик поддерживает три режима для приложений .NET MAUI в iOS и Mac Catalyst:

  • Не ссылайтесь. Отключение связывания гарантирует, что сборки не изменяются.
  • Связывание только сборок пакета SDK. В этом режиме компоновщик оставляет сборки неуправляемыми и уменьшает размер сборок ПАКЕТА SDK, удаляя типы и элементы, которые не использует ваше приложение.
  • Связывание всех сборок. При связывании всех сборок компоновщик выполняет дополнительные оптимизации, чтобы сделать приложение максимально небольшим. Он изменяет промежуточный код исходного кода, который может нарушить приложение, если вы используете функции с помощью подхода, который статический анализ компоновщика не может обнаружить. В таких случаях может потребоваться внести изменения в исходный код, чтобы приложение работало правильно.

Поведение компоновщика можно настроить для каждой конфигурации сборки приложения.

Предупреждение

Включение компоновщика для конфигурации отладки приложения может препятствовать отладке, так как это может удалить методы доступа к свойствам, позволяющие проверить состояние объектов.

Чтобы настроить поведение компоновщика в Visual Studio Code, необходимо добавить $(MtouchLink) свойство сборки в группу свойств в CSPROJ-файле приложения. Это свойство сборки должно иметь значение None, SdkOnlyили Full:

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0-maccatalyst|AnyCPU'">
  <MtouchLink>SdkOnly</MtouchLink>
</PropertyGroup>

Кроме того, можно указать поведение компоновщика с помощью интерфейса командной строки при создании и публикации приложения. Дополнительные сведения см. в статье "Публикация приложения .NET MAUI Mac Catalyst".

Внимание

$(MtouchLink) Свойство сборки можно задать отдельно для каждой конфигурации сборки для приложения.

Сохранение кода

При использовании компоновщика иногда удаляется код, который может вызываться динамически, даже косвенно. Компоновщику можно указать сохранить элементы, заметив их атрибутом 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 метод хранится. Без атрибута связывание удаляется Helper MyAssembly или удаляется 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> файле проекта:

<ItemGroup>
  <TrimmerRootAssembly Include="MyAssembly" />
</ItemGroup>

Примечание.

Расширение .dll не требуется при настройке TrimmerRootAssembly свойства MSBuild.

Если компоновщик пропускает сборку, он считается корневым, что означает, что она и все его статически понятные зависимости сохраняются. Можно пропустить дополнительные сборки, добавив в него <ItemGroup>дополнительные TrimmerRootAssembly свойства MSBuild.

Сохранение сборок, типов и элементов

Компоновщик можно передать XML-файл описания, указывающий, какие сборки, типы и члены должны храниться.

Чтобы исключить член из процесса связывания при связывании всех сборок, задайте TrimmerRootDescriptor свойство MSBuild в <ItemGroup> теге в файле проекта 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>

Это помечает сборку как "обрезаемую" и включает предупреждения обрезки для этого проекта. Будучи "обрезаемым" означает, что сборка считается совместимой с обрезкой и не должна иметь предупреждений обрезки при сборке сборки. При использовании в обрезаном приложении неиспользуемые элементы сборки удаляются в окончательных выходных данных.

IsTrimmable Задание свойства true MSBuild в файле проекта вставляет атрибут в сборку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>

В этом параметре отображаются все подробные предупреждения, а не сворачивание их на одну сборку.