Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Примечание.
Это не последняя версия этой статьи. В текущей версии см. версию .NET 10 этой статьи.
Предупреждение
Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в политике поддержки .NET и .NET Core. В текущей версии см. версию .NET 10 этой статьи.
В этой статье объясняется, как управлять триммером промежуточного Blazor языка (IL) при создании приложения.
Blazor WebAssembly выполняет обрезку промежуточного языка (IL) для уменьшения размера публикуемых выходных данных. Обрезка возникает при публикации приложения.
Степень детализации триммера по умолчанию
Гранулярность обрезки по умолчанию для Blazor приложений partial — это означает, что обрезаются только основные библиотеки каркаса и библиотеки, которые явно включили поддержку обрезки. Полная обрезка не поддерживается.
Дополнительные сведения см. в разделе "Параметры обрезки" (документация по .NET).
Настройка
Сведения о настройке триммера IL см . в статье "Параметры обрезки " в документации по основам .NET, которая содержит рекомендации по следующим темам:
- Отключение обрезки для всего приложения со свойством
<PublishTrimmed>в файле проекта. - Контроль того, как агрессивно неиспользуемый IL удаляется триммером IL.
- Остановите триммер IL от обрезки определенных сборок.
- "Корневые" сборки для усечения.
- Отображение предупреждений для отраженных типов путем присвоения свойству
<SuppressTrimAnalysisWarnings>значенияfalseв файле проекта. - Управление обрезкой символов и поддержкой отладчика.
- Настройка функций триммера IL для обрезки функций библиотеки платформы.
Если степень детализацииpartial триммера равна значению по умолчанию, триммер IL обрезает библиотеку базовых классов и любые другие сборки, помеченные как триммируемые. Чтобы включить обрезку в любом из проектов библиотеки классов приложения, установите для свойства MSBuild <IsTrimmable> значение true в этих проектах.
<PropertyGroup>
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>
Рекомендации, относящиеся к библиотекам .NET, см. в статье "Подготовка библиотек .NET для обрезки".
Сбой сохранения типов, используемых опубликованным приложением
Обрезка может иметь негативные последствия для опубликованного приложения, что приводит к ошибкам среды выполнения, даже несмотря на настройку <PublishTrimmed> свойстваfalse в файле проекта. В приложениях, использующих отражение, триммер IL часто не может определить необходимые типы для отражения среды выполнения и обрезает их или обрезает имена параметров из методов. Это может произойти со сложными типами фреймворков, используемыми для JS взаимодействия, сериализации и десериализации JSON, а также других операций.
Триммер IL также не может реагировать на динамическое поведение приложения во время выполнения. Чтобы обеспечить правильную работу обрезанного приложения после его развертывания, следует часто тестировать публикуемые выходные данные во время разработки.
Рассмотрим следующий пример, который выполняет десериализацию JSON в Tuple<T1,T2> коллекцию (List<Tuple<string, string>>).
TrimExample.razor:
@page "/trim-example"
@using System.Diagnostics.CodeAnalysis
@using System.Text.Json
<h1>Trim Example</h1>
<ul>
@foreach (var item in @items)
{
<li>@item.Item1, @item.Item2</li>
}
</ul>
@code {
private List<Tuple<string, string>> items = [];
[StringSyntax(StringSyntaxAttribute.Json)]
private const string data =
"""[{"item1":"1:T1","item2":"1:T2"},{"item1":"2:T1","item2":"2:T2"}]""";
protected override void OnInitialized()
{
JsonSerializerOptions options = new() { PropertyNameCaseInsensitive = true };
items = JsonSerializer
.Deserialize<List<Tuple<string, string>>>(data, options)!;
}
}
Предыдущий компонент обычно выполняется при локальном запуске приложения и создает следующий отрисованный список:
• 1:T1, 1:T2
• 2:T2, 2:T2
Когда приложение опубликовано, обрезается из приложения, Tuple<T1,T2> даже несмотря на настройку <PublishTrimmed> свойства false в файле проекта. Доступ к компоненту вызывает следующее исключение:
crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: ConstructorContainsNullParameterNames, System.Tuple`2[System.String,System.String]
System.NotSupportedException: ConstructorContainsNullParameterNames, System.Tuple`2[System.String,System.String]
Чтобы устранить потерянные типы, рассмотрите возможность применения одного из следующих подходов.
Пользовательские типы
Чтобы избежать проблем с обрезкой .NET в сценариях, основанных на отражении, таких как JS взаимодействие и сериализация JSON, используйте настраиваемые типы, определенные в неподлежащих обрезке библиотеках, или сохраняйте типы с помощью конфигурации компоновщика.
Следующие изменения создают тип StringTuple для использования этим компонентом.
StringTuple.cs:
[method: SetsRequiredMembers]
public sealed class StringTuple(string item1, string item2)
{
public required string Item1 { get; init; } = item1;
public required string Item2 { get; init; } = item2;
}
Компонент изменяется для использования StringTuple типа:
- private List<Tuple<string, string>> items = [];
+ private List<StringTuple> items = [];
- items = JsonSerializer.Deserialize<List<Tuple<string, string>>>(data, options)!;
+ items = JsonSerializer.Deserialize<List<StringTuple>>(data, options)!;
Так как пользовательские типы, определенные в сборках, которые не подлежат обрезке, не обрезаются Blazor при публикации приложения, компонент функционирует корректно после публикации приложения.
Если вы предпочитаете использовать типы платформ, несмотря на нашу рекомендацию, используйте любой из следующих подходов:
Если вы предпочитаете использовать типы платформ, несмотря на нашу рекомендацию, сохраните тип как динамическую зависимость.
Сохраняйте тип как динамическую зависимость
Создайте динамическую зависимость, чтобы сохранить тип с помощью атрибута[DynamicDependency].
Если еще нет, добавьте директиву @using для System.Diagnostics.CodeAnalysis:
@using System.Diagnostics.CodeAnalysis
Добавьте атрибут [DynamicDependency] для сохранения Tuple<T1,T2>:
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors,
+ typeof(Tuple<string, string>))]
private List<Tuple<string, string>> items = [];
Использование корневого дескриптора
Корневой дескриптор может сохранить тип.
Добавьте файл в корневой ILLink.Descriptors.xml каталог приложения† с типом:
<linker>
<assembly fullname="System.Private.CoreLib">
<type fullname="System.Tuple`2" preserve="all" />
</assembly>
</linker>
† Корневой каталог приложения ссылается на корень Blazor WebAssembly приложения или корневой каталог .Client проекта Blazor Web App (.NET 8 или более поздней версии).
TrimmerRootDescriptor Добавьте элемент в файл проекта приложения, ссылающийся ILLink.Descriptors.xml на файл:
<ItemGroup>
<TrimmerRootDescriptor Include="$(MSBuildThisFileDirectory)ILLink.Descriptors.xml" />
</ItemGroup>
Файл проекта — это файл Blazor WebAssembly проекта приложения или файла .Client проекта проекта проекта Blazor Web App (.NET 8 или более поздней версии).
Обходное решение в .NET 8
В качестве обходного _ExtraTrimmerArgs решения в .NET 8 можно добавить свойство MSBuild, заданное --keep-metadata parametername в файл проекта приложения, чтобы сохранить имена параметров во время обрезки:
<PropertyGroup>
<_ExtraTrimmerArgs>--keep-metadata parametername</_ExtraTrimmerArgs>
</PropertyGroup>
Дополнительные ресурсы
ASP.NET Core