AspectGenerator 0.0.3-preview
This is a prerelease version of AspectGenerator.
There is a newer prerelease version of this package available.
See the version list below for details.
See the version list below for details.
dotnet add package AspectGenerator --version 0.0.3-preview
NuGet\Install-Package AspectGenerator -Version 0.0.3-preview
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="AspectGenerator" Version="0.0.3-preview" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add AspectGenerator --version 0.0.3-preview
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: AspectGenerator, 0.0.3-preview"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install AspectGenerator as a Cake Addin #addin nuget:?package=AspectGenerator&version=0.0.3-preview&prerelease // Install AspectGenerator as a Cake Tool #tool nuget:?package=AspectGenerator&version=0.0.3-preview&prerelease
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Aspect Generator
The Aspect Generator can help you easily create your own aspects.
[!WARNING] Interceptors are an experimental compiler feature planned to ship in .NET 8 (with support for C# only). The feature may be subject to breaking changes or removal in a future release.
Download and Install
Install nuget
> dotnet add package AspectGenerator
Modify your project file
<PropertyGroup>
...
<LangVersion>preview</LangVersion>
<InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);AspectGenerator</InterceptorsPreviewNamespaces>
</PropertyGroup>
OpenTelemetry Aspect example
Create OpenTelemetryFactory and Metrics aspect:
using System;
using System.Diagnostics;
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
namespace AspectGenerator
{
/// <summary>
/// Initializes OpenTelemetry.
/// </summary>
static class OpenTelemetryFactory
{
public static TracerProvider? Create()
{
return Sdk.CreateTracerProviderBuilder()
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MySample"))
.AddSource("Sample.Aspect")
.AddConsoleExporter()
.Build();
}
}
/// <summary>
/// Metrics aspect.
/// </summary>
[Aspect(
// Specify the name of the method used in the 'using' statement
// that returns an IDisposable object.
OnUsing = nameof(OnUsing)
)]
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
sealed class MetricsAttribute : Attribute
{
static readonly ActivitySource _activitySource = new("Sample.Aspect");
public static Activity? OnUsing(InterceptInfo info)
{
return _activitySource.StartActivity(info.MemberInfo.Name);
}
}
}
Use it:
using System;
using System.Threading;
using Aspects;
namespace OpenTelemetryAspect
{
static class Program
{
static void Main()
{
using var _ = OpenTelemetryFactory.Create();
Method1();
Method2();
Method1();
}
[Metrics]
public static void Method1()
{
Thread.Sleep(100);
}
[Metrics]
public static void Method2()
{
Thread.Sleep(200);
}
}
}
Application output:
Activity.TraceId: d47417e726824c7b39055efb4685a9dd
Activity.SpanId: 12fbf29f5b622e13
Activity.TraceFlags: Recorded
Activity.ActivitySourceName: Sample.Aspect
Activity.DisplayName: Method1
Activity.Kind: Internal
Activity.StartTime: 2023-11-22T00:50:15.9079068Z
Activity.Duration: 00:00:00.1016180
Resource associated with Activity:
service.name: MySample
service.instance.id: 86dbd377-c850-42a3-b878-be07de30faf1
telemetry.sdk.name: opentelemetry
telemetry.sdk.language: dotnet
telemetry.sdk.version: 1.6.0
Activity.TraceId: b90735bfb52cb0b52a504d02bc5ead2e
Activity.SpanId: 75109ef3af25a3e9
Activity.TraceFlags: Recorded
Activity.ActivitySourceName: Sample.Aspect
Activity.DisplayName: Method2
Activity.Kind: Internal
Activity.StartTime: 2023-11-22T00:50:16.0360160Z
Activity.Duration: 00:00:00.2058166
Resource associated with Activity:
service.name: MySample
service.instance.id: 86dbd377-c850-42a3-b878-be07de30faf1
telemetry.sdk.name: opentelemetry
telemetry.sdk.language: dotnet
telemetry.sdk.version: 1.6.0
Activity.TraceId: e9653008f381b6330a8e538e02b7a61d
Activity.SpanId: be3d7cd1d4376bd7
Activity.TraceFlags: Recorded
Activity.ActivitySourceName: Sample.Aspect
Activity.DisplayName: Method1
Activity.Kind: Internal
Activity.StartTime: 2023-11-22T00:50:16.2517480Z
Activity.Duration: 00:00:00.1135186
Resource associated with Activity:
service.name: MySample
service.instance.id: 86dbd377-c850-42a3-b878-be07de30faf1
telemetry.sdk.name: opentelemetry
telemetry.sdk.language: dotnet
telemetry.sdk.version: 1.6.0
Generated code:
// <auto-generated/>
#pragma warning disable
#nullable enable
using System;
using SR = System.Reflection;
using SLE = System.Linq.Expressions;
using SCG = System.Collections.Generic;
namespace Aspects
{
static partial class Interceptors
{
static SR.MethodInfo GetMethodInfo(SLE.Expression expr)
{
return expr switch
{
SLE.MethodCallExpression mc => mc.Method,
_ => throw new InvalidOperationException()
};
}
static SR.MethodInfo MethodOf<T>(SLE.Expression<Func<T>> func) => GetMethodInfo(func.Body);
static SR.MethodInfo MethodOf (SLE.Expression<Action> func) => GetMethodInfo(func.Body);
static SR. MemberInfo Method1_Interceptor_MemberInfo = MethodOf(() => OpenTelemetryAspect.Program.Method1());
static SCG.Dictionary<string,object?> Method1_Interceptor_AspectArguments_0 = new ()
{
};
//
/// <summary>
/// Intercepts OpenTelemetryAspect.Program.Method1().
/// </summary>
//
// Intercepts Method1().
[System.Runtime.CompilerServices.InterceptsLocation(@"P:\AspectGenerator\Examples\OpenTelemetryAspect\Program.cs", line: 14, character: 4)]
//
// Intercepts Method1().
[System.Runtime.CompilerServices.InterceptsLocation(@"P:\AspectGenerator\Examples\OpenTelemetryAspect\Program.cs", line: 16, character: 4)]
//
[System.Runtime.CompilerServices.CompilerGenerated]
//[System.Diagnostics.DebuggerStepThrough]
public static void Method1_Interceptor()
{
// Aspects.MetricsAttribute
//
var __info__0 = new Aspects.InterceptInfo<Void>
{
MemberInfo = Method1_Interceptor_MemberInfo,
AspectType = typeof(Aspects.MetricsAttribute),
AspectArguments = Method1_Interceptor_AspectArguments_0,
};
using (Aspects.MetricsAttribute.OnUsing(__info__0))
{
OpenTelemetryAspect.Program.Method1();
}
}
static SR. MemberInfo Method2_Interceptor_MemberInfo = MethodOf(() => OpenTelemetryAspect.Program.Method2());
static SCG.Dictionary<string,object?> Method2_Interceptor_AspectArguments_0 = new ()
{
};
//
/// <summary>
/// Intercepts OpenTelemetryAspect.Program.Method2().
/// </summary>
//
// Intercepts Method2().
[System.Runtime.CompilerServices.InterceptsLocation(@"P:\AspectGenerator\Examples\OpenTelemetryAspect\Program.cs", line: 15, character: 4)]
//
[System.Runtime.CompilerServices.CompilerGenerated]
//[System.Diagnostics.DebuggerStepThrough]
public static void Method2_Interceptor()
{
// Aspects.MetricsAttribute
//
var __info__0 = new Aspects.InterceptInfo<Void>
{
MemberInfo = Method2_Interceptor_MemberInfo,
AspectType = typeof(Aspects.MetricsAttribute),
AspectArguments = Method2_Interceptor_AspectArguments_0,
};
using (Aspects.MetricsAttribute.OnUsing(__info__0))
{
OpenTelemetryAspect.Program.Method2();
}
}
}
}
More advanced vertion of the Metrics aspect can also set activity status.
[Aspect(
OnUsing = nameof(OnUsing),
OnFinally = nameof(OnFinally)
)]
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
sealed class MetricsAttribute : Attribute
{
static readonly ActivitySource _activitySource = new("Sample.Aspect");
public static Activity? OnUsing(InterceptInfo info)
{
var activity = _activitySource.StartActivity(info.MemberInfo.Name);
info.Tag = activity;
return activity;
}
public static void OnFinally(InterceptInfo info)
{
if (info is { Tag: Activity activity, Exception: var ex })
activity.SetStatus(ex is null ? ActivityStatusCode.Ok : ActivityStatusCode.Error);
}
}
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- Microsoft.CodeAnalysis.CSharp.Workspaces (>= 4.7.0)
- PolySharp (>= 1.13.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
0.0.9-preview | 152 | 12/28/2023 |
0.0.8-preview | 107 | 12/13/2023 |
0.0.7-preview | 80 | 12/12/2023 |
0.0.5-preview | 100 | 12/4/2023 |
0.0.4-preview | 81 | 11/27/2023 |
0.0.3-preview | 77 | 11/23/2023 |
0.0.1-preview | 64 | 11/22/2023 |