Patterns and techniques for evaluating and improving AI agent outputs.
日本語の概要は準備中です。原文の説明を表示しています。
Trims .NET 8+ apps and libraries. Annotations, ILLink descriptors, IL2xxx warnings, IsTrimmable.
インストールする前に、エージェントに与えられる指示の中身を確認できます。
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 -->
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
<!-- Optional: also enable AOT analyzer if targeting AOT -->
<EnableAotAnalyzer>true</EnableAotAnalyzer>
</PropertyGroup>
```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
<PropertyGroup>
<!-- Declare the library is trim-safe (auto-enables trim analyzer) -->
<IsTrimmable>true</IsTrimmable>
<!-- Declare AOT compatibility (auto-enables AOT analyzer) -->
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>
```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<T>() where T : class => _serviceProvider.GetRequiredService<T>();
// 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
<!-- ILLink.Descriptors.xml -->
<linker>
<!-- Preserve specific types -->
<assembly fullname="MyApp">
<type fullname="MyApp.Models.PluginConfig" preserve="all" />
<type fullname="MyApp.Services.LegacyAdapter">
<method name="Initialize" />
<method name="ProcessRequest" />
</type>
</assembly>
<!-- Preserve an entire third-party assembly -->
<assembly fullname="LegacyLibrary" preserve="all" />
</linker>
```text
### Registration
```xml
<!-- In .csproj -->
<ItemGroup>
<TrimmerRootDescriptor Include="ILLink.Descriptors.xml" />
</ItemGroup>
```csharp
### Alternative: TrimmerRootAssembly
For entire assemblies that must not be trimmed:
```xml
<ItemGroup>
<!-- Preserve entire assembly (no trimming at all) -->
<TrimmerRootAssembly Include="LegacyLibrary" />
</ItemGroup>
```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 `<IsTrimmable>true</IsTrimmable>` 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
<!-- Library .csproj -->
<PropertyGroup>
<!-- Auto-enables trim analyzer -->
<IsTrimmable>true</IsTrimmable>
<!-- Auto-enables AOT analyzer; implies IsTrimmable in .NET 8+ -->
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>
```text
### Annotating Public APIs
```csharp
// Method that uses reflection internally -- annotate honestly
[RequiresUnreferencedCode(
"Uses reflection to discover plugin types. " +
"Use RegisterPlugin<T>() 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<T>();
}
```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"
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Patterns and techniques for evaluating and improving AI agent outputs.
日本語の概要は準備中です。原文の説明を表示しています。
Comprehensive AI prompt engineering safety review and improvement prompt. Analyzes prompts for safety, bias, security vulnerabilities, and effectiveness while providing detailed improvement recommendations.
日本語の概要は準備中です。原文の説明を表示しています。
Use when user requests research requiring multiple sources, comprehensive analysis, or synthesis across topics - technical research, domain knowledge gathering, market analysis, or learning about complex subjects
日本語の概要は準備中です。原文の説明を表示しています。
AI-powered wiki generation for code repositories with commands, agents, and skills
日本語の概要は準備中です。原文の説明を表示しています。
Use when building .NET 10 or C# 14 applications; when using minimal APIs, modular monolith patterns, or feature folders; when implementing HTTP resilience, Options pattern, Channels, or validation; when seeing outdated patterns like old extension method syntax
日本語の概要は準備中です。原文の説明を表示しています。
Implements accessible .NET UI. SemanticProperties, ARIA, AutomationPeer, testing per platform.
日本語の概要は準備中です。原文の説明を表示しています。