用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/rudironsoni/Synaxis --skill dotnet-trimming命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
AI-powered wiki generation for code repositories with commands, agents, and skills
Routes .NET/C# work to domain skills. Loads coding-standards for code paths.
Skill manifest management for dotnet-agent-harness. Tracks skill dependencies, conflicts, version compatibility, and provides validation and resolution tools. Triggers on: skill manifest, dependency resolution, skill compatibility, version conflicts, build manifest, validate dependencies.
基于 SOC 职业分类
正在显示 SKILL.md
| name | dotnet-trimming |
| category | performance |
| subcategory | aot |
| description | Trims .NET 8+ apps and libraries. Annotations, ILLink descriptors, IL2xxx warnings, IsTrimmable. |
| license | MIT |
| targets | ["*"] |
| tags | ["aot","dotnet","skill"] |
| version | 0.0.1 |
| author | dotnet-agent-harness |
| invocable | true |
| claudecode | {"allowed-tools":["Read","Grep","Glob","Bash","Write","Edit"]} |
| codexcli | {"short-description":".NET skill guidance for aot tasks"} |
| opencode | {"allowed-tools":["Read","Grep","Glob","Bash","Write","Edit"]} |
| copilot | {} |
| geminicli | {} |
| antigravity | {} |
Trim-safe development for .NET 8+ applications and libraries: trimming annotations ([RequiresUnreferencedCode],
[DynamicallyAccessedMembers], [DynamicDependency]), ILLink descriptor XML for type preservation, TrimmerSingleWarn
for granular diagnostics, testing trimmed output, fixing IL2xxx/IL3xxx warnings, and library authoring with
IsTrimmable.
Version assumptions: .NET 8.0+ baseline. Trimming shipped in .NET 6, but .NET 8 provides the most complete annotation surface and analyzer coverage. .NET 9 improved warning accuracy and library compat.
Cross-references: [skill:dotnet-native-aot] for AOT compilation pipeline, [skill:dotnet-aot-architecture] for AOT-safe design patterns, [skill:dotnet-serialization] for AOT-safe serialization, [skill:dotnet-csharp-source-generators] for source gen as trimming enabler.
Apps and libraries use different MSBuild properties for trimming. This distinction is critical -- using the wrong property causes subtle issues.
<PropertyGroup>
<!-- Enable trimming on publish -->
<PublishTrimmed>true</PublishTrimmed>
<!-- Enable trim analyzer during development -->
true
true
```text
`PublishTrimmed` tells the linker to remove unreachable code when publishing. `EnableTrimAnalyzer` enables Roslyn analyzers that warn about trim-unsafe patterns during development.
### For Libraries
```xml
true
true
```text
**Key difference:** Libraries do not set `PublishTrimmed` -- they are not published as standalone applications. `IsTrimmable` tells consumers that the library's public API is annotated for trimming safety. Setting `IsTrimmable` automatically enables the trim analyzer for the library project.
| Property | Project Type | Effect |
|----------|-------------|--------|
| `PublishTrimmed` | App | Trims on publish, enables linker |
| `EnableTrimAnalyzer` | App | Enables trim warnings during build |
| `IsTrimmable` | Library | Declares trim-safe, auto-enables analyzer |
| `IsAotCompatible` | Library | Declares AOT-safe, auto-enables AOT analyzer |
| `PublishAot` | App | Enables AOT (implies `PublishTrimmed`) |
---
## Trimming Annotations
.NET provides attributes to annotate code that interacts with reflection, helping the trimmer understand what to preserve.
### `[RequiresUnreferencedCode]`
Marks a method as unsafe for trimming. The trimmer and analyzer produce IL2026 warnings when this method is called from trim-safe code.
```csharp
[RequiresUnreferencedCode("Uses reflection to discover plugins")]
public IPlugin LoadPlugin(string typeName)
{
// Prefer factory/DI pattern for AOT/trimming compatibility
// Resolve via a factory or DI so the trimmer understands the type flow and avoids Activator usage.
// Example: register factories at startup and resolve by key/type.
var factory = _pluginFactory.Resolve(typeName) ?? throw new InvalidOperationException($"Type {typeName} not found");
return factory.Create();
}
```text
### `[DynamicallyAccessedMembers]`
Tells the trimmer which members of a type are accessed via reflection, so they are preserved:
```csharp
public T CreateInstance<[DynamicallyAccessedMembers(
DynamicallyAccessedMemberTypes.PublicConstructors)] T>()
where T : class
// AOT-safe alternative: use a generic factory resolved by DI
// Example:
// public T CreateInstance() where T : class => _serviceProvider.GetRequiredService();
// The trimmer understands DI-registered concrete types and avoids runtime activator calls.
```text
### `[DynamicDependency]`
Explicitly preserves a specific member from trimming:
```csharp
// Preserve a method that is only called via reflection
[DynamicDependency(nameof(OnConfigChanged), typeof(ConfigWatcher))]
public void StartWatching() { /* reflects on OnConfigChanged */ }
// Preserve all public properties (e.g., for serialization)
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties,
typeof(LegacyDto))]
public void SerializeLegacy(LegacyDto dto) { /* ... */ }
```text
### `[UnconditionalSuppressMessage]`
Suppresses a specific trim warning when you have verified the code is safe despite the analyzer's concern:
```csharp
[UnconditionalSuppressMessage("Trimming",
"IL2026:RequiresUnreferencedCode",
Justification = "Type is preserved via ILLink descriptor")]
// TODO: Audit suppression - add justification or remove
public void CallLegacyCode() { /* ... */ }
```text
Use sparingly -- only when you have verified safety through ILLink descriptors or other means.
---
## ILLink Descriptors
ILLink descriptor XML files tell the trimmer to preserve types, methods, or entire assemblies. **Do not use legacy RD.xml** -- it is a .NET Native/UWP format that is silently ignored by modern .NET trimming.
### Descriptor Format
```xml
```text
### Registration
```xml
```csharp
### Alternative: TrimmerRootAssembly
For entire assemblies that must not be trimmed:
```xml
```text
---
## TrimmerSingleWarn
By default, the trimmer groups warnings per assembly, showing one summary line. `TrimmerSingleWarn=false` shows every individual warning, which is essential for fixing trim issues.
```bash
# Default: one warning per assembly (hard to debug)
dotnet publish -c Release /p:PublishTrimmed=true
# warning IL2104: Assembly 'MyApp' produced trim warnings
# Detailed: per-occurrence warnings (easier to fix)
dotnet publish -c Release /p:PublishTrimmed=true /p:TrimmerSingleWarn=false
# warning IL2026: MyApp.PluginLoader.LoadPlugin(...) requires unreferenced code
# warning IL2057: Unrecognized value passed to Type.GetType(...)
# Analysis without publishing
dotnet build /p:EnableTrimAnalyzer=true /p:TrimmerSingleWarn=false
```text
---
## IL2xxx/IL3xxx Warning Reference
### Trim Warnings (IL2xxx)
| Code | Meaning | Fix |
|------|---------|-----|
| IL2026 | Method has `[RequiresUnreferencedCode]` | Replace with trim-safe alternative or add descriptor |
| IL2046 | Trim attribute mismatch on override | Match annotation from base type |
| IL2057 | Unrecognized `Type.GetType()` argument | Use compile-time known type or `[DynamicDependency]` |
| IL2060 | `MakeGenericType` call with unknown type | Use concrete generic instantiations |
| IL2062 | Value passed to `[DynamicallyAccessedMembers]` parameter has no annotation | Add `[DynamicallyAccessedMembers]` to the source |
| IL2067 | Parameter mismatch for `[DynamicallyAccessedMembers]` | Ensure annotations flow correctly through call chain |
| IL2070 | `this` parameter of `Type.GetProperties()` etc. not annotated | Add `[DynamicallyAccessedMembers]` constraint |
| IL2072 | Return value of a method not annotated | Annotate return type with `[DynamicallyAccessedMembers]` |
| IL2104 | Assembly produced trim warnings (summary) | Use `TrimmerSingleWarn=false` for details |
### AOT Warnings (IL3xxx)
| Code | Meaning | Fix |
|------|---------|-----|
| IL3050 | Method has `[RequiresDynamicCode]` | Replace with source-gen or static alternative |
| IL3051 | `[RequiresDynamicCode]` annotation mismatch | Match annotation from base type |
| IL3052 | COM interop with dynamic code | Use `[LibraryImport]` with static marshalling |
---
## Testing Trimmed Output
### Publish and Test
```bash
# Publish with trimming
dotnet publish -c Release -r linux-x64 /p:PublishTrimmed=true
# Run the trimmed binary
./bin/Release/net8.0/linux-x64/publish/MyApp
# Verify functionality:
# 1. All endpoints respond correctly
# 2. JSON deserialization produces populated objects
# 3. DI-resolved services function
# 4. No MissingMethodException or MissingMetadataException
```json
### Trim Test in CI
```bash
# CI script: publish trimmed and run integration tests
dotnet publish src/MyApp -c Release -r linux-x64 /p:PublishTrimmed=true -o ./publish
# Run smoke tests against trimmed binary
./publish/MyApp &
APP_PID=$!
sleep 3
curl -f http://localhost:8080/health/live || (kill $APP_PID; exit 1)
curl -f http://localhost:8080/api/products || (kill $APP_PID; exit 1)
kill $APP_PID
```text
### Trim Warning CI Gate
```bash
# Fail CI if any trim warnings exist
dotnet build /p:EnableTrimAnalyzer=true /p:TrimmerSingleWarn=false \
/warnaserror:IL2026,IL2057,IL2060,IL2067,IL2070,IL3050
```bash
---
## Library Authoring for Trimming
### Making a Library Trim-Safe
1. Set `true` in the library `.csproj`
2. Annotate all reflection-using APIs with `[RequiresUnreferencedCode]`
3. Add `[DynamicallyAccessedMembers]` to parameters that receive types used reflectively
4. Replace reflection with source generators where possible
5. Test by consuming the library from a trimmed application
```xml
true
true
```text
### Annotating Public APIs
```csharp
// Method that uses reflection internally -- annotate honestly
[RequiresUnreferencedCode(
"Uses reflection to discover plugin types. " +
"Use RegisterPlugin() for trim-safe plugin registration.")]
public IPlugin LoadPlugin(string typeName) { /* ... */ }
// Trim-safe alternative
public void RegisterPlugin<[DynamicallyAccessedMembers(
DynamicallyAccessedMemberTypes.PublicConstructors)] T>()
where T : class, IPlugin
{
_plugins[typeof(T).Name] = () => (IPlugin)Activator.CreateInstance();
}
```text
### Conditional APIs
Provide both reflection-based and trim-safe APIs when possible:
```csharp
public class ServiceRegistry
{
// Trim-safe: explicit type
public void Register<[DynamicallyAccessedMembers(
DynamicallyAccessedMemberTypes.PublicConstructors)] TService,
TImplementation>()
where TImplementation : class, TService
{ /* ... */ }
// Not trim-safe: assembly scanning
[RequiresUnreferencedCode("Scans assembly for service types")]
public void RegisterFromAssembly(Assembly assembly)
{ /* ... */ }
}
```text
---
## Agent Gotchas
1. **Do not use `PublishTrimmed` in library projects.** Libraries use `IsTrimmable` to declare they are trim-safe. `PublishTrimmed` is for applications.
2. **Do not use RD.xml for type preservation.** RD.xml is a .NET Native/UWP format that is silently ignored by modern .NET trimming. Use ILLink descriptor XML files instead.
3. **Do not suppress trim warnings without verifying safety.** `[UnconditionalSuppressMessage]` hides warnings but does not fix the underlying issue. Only suppress when you have verified the code is safe (e.g., via ILLink descriptors).
4. **Do not forget `TrimmerSingleWarn=false` when debugging trim issues.** Without it, you get one summary warning per assembly, making it impossible to find the specific problematic call site.
5. **Do not confuse `IsTrimmable` with `PublishTrimmed`.** `IsTrimmable` declares a library is trim-safe and enables the analyzer. `PublishTrimmed` enables the linker in applications. They serve different purposes.
6. **Do not add `[RequiresUnreferencedCode]` to methods that do not use reflection.** The annotation propagates virally -- callers must also be annotated or suppress the warning. Only annotate methods that actually use trim-unsafe reflection.
---
## References
- [Trim self-contained applications](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options)
- [Prepare libraries for trimming](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/prepare-libraries-for-trimming)
- [Introduction to trim warnings](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/fixing-warnings)
- [Trimming annotation attributes](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/prepare-libraries-for-trimming#trimming-annotation-attributes)
- [ILLink descriptor format](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options#descriptor-format)
Primary approach: Use Serena symbol operations for efficient code navigation:
serena_find_symbol instead of text searchserena_get_symbols_overview for file organizationserena_find_referencing_symbols for impact analysisserena_replace_symbol_body for clean modificationsWhen to use Serena vs traditional tools:
Example workflow:
# Instead of:
Read: src/Services/OrderService.cs
Grep: "public void ProcessOrder"
# Use:
serena_find_symbol: "OrderService/ProcessOrder"
serena_get_symbols_overview: "src/Services/OrderService.cs"