Skip to content

Commit

Permalink
Updates.
Browse files Browse the repository at this point in the history
  • Loading branch information
igor-tkachev committed Dec 6, 2023
1 parent 97dc9b6 commit 7c59303
Show file tree
Hide file tree
Showing 10 changed files with 206 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,33 @@

namespace AspectGenerator
{
#if !AG_NOT_GENERATE_API

[Aspect]
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
#if AG_PUBLIC
public
#endif
sealed class AspectAttribute : Attribute
{
public string? OnInit { get; set; }
public string? OnUsing { get; set; }
public string? OnUsingAsync { get; set; }
public string? OnBeforeCall { get; set; }
public string? OnBeforeCallAsync { get; set; }
public string? OnAfterCall { get; set; }
public string? OnAfterCallAsync { get; set; }
public string? OnCatch { get; set; }
public string? OnCatchAsync { get; set; }
public string? OnFinally { get; set; }
public string? OnFinallyAsync { get; set; }
public bool PassArguments { get; set; }
public string? OnInit { get; set; }
public string? OnUsing { get; set; }
public string? OnUsingAsync { get; set; }
public string? OnBeforeCall { get; set; }
public string? OnBeforeCallAsync { get; set; }
public string? OnAfterCall { get; set; }
public string? OnAfterCallAsync { get; set; }
public string? OnCatch { get; set; }
public string? OnCatchAsync { get; set; }
public string? OnFinally { get; set; }
public string? OnFinallyAsync { get; set; }
public string[]? InterceptedMethods { get; set; }
public bool PassArguments { get; set; }
}

#if AG_PUBLIC
public
#endif
enum InterceptType
{
OnInit,
Expand All @@ -33,6 +42,9 @@ enum InterceptType
OnFinally
}

#if AG_PUBLIC
public
#endif
enum InterceptResult
{
Continue,
Expand All @@ -41,10 +53,16 @@ enum InterceptResult
IgnoreThrow = Return
}

#if AG_PUBLIC
public
#endif
struct Void
{
}

#if AG_PUBLIC
public
#endif
abstract class InterceptInfo
{
public object? Tag;
Expand All @@ -59,16 +77,25 @@ abstract class InterceptInfo
public System.Collections.Generic.Dictionary<string,object?> AspectArguments;
}

#if AG_PUBLIC
public
#endif
class InterceptInfo<T> : InterceptInfo
{
public T ReturnValue;
}
}

#endif

#if !AG_NOT_GENERATE_InterceptsLocationAttribute

namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
sealed class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute
{
}
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,33 @@

namespace AspectGenerator
{
#if !AG_NOT_GENERATE_API

[Aspect]
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
#if AG_PUBLIC
public
#endif
sealed class AspectAttribute : Attribute
{
public string? OnInit { get; set; }
public string? OnUsing { get; set; }
public string? OnUsingAsync { get; set; }
public string? OnBeforeCall { get; set; }
public string? OnBeforeCallAsync { get; set; }
public string? OnAfterCall { get; set; }
public string? OnAfterCallAsync { get; set; }
public string? OnCatch { get; set; }
public string? OnCatchAsync { get; set; }
public string? OnFinally { get; set; }
public string? OnFinallyAsync { get; set; }
public bool PassArguments { get; set; }
public string? OnInit { get; set; }
public string? OnUsing { get; set; }
public string? OnUsingAsync { get; set; }
public string? OnBeforeCall { get; set; }
public string? OnBeforeCallAsync { get; set; }
public string? OnAfterCall { get; set; }
public string? OnAfterCallAsync { get; set; }
public string? OnCatch { get; set; }
public string? OnCatchAsync { get; set; }
public string? OnFinally { get; set; }
public string? OnFinallyAsync { get; set; }
public string[]? InterceptedMethods { get; set; }
public bool PassArguments { get; set; }
}

#if AG_PUBLIC
public
#endif
enum InterceptType
{
OnInit,
Expand All @@ -33,6 +42,9 @@ enum InterceptType
OnFinally
}

#if AG_PUBLIC
public
#endif
enum InterceptResult
{
Continue,
Expand All @@ -41,10 +53,16 @@ enum InterceptResult
IgnoreThrow = Return
}

#if AG_PUBLIC
public
#endif
struct Void
{
}

#if AG_PUBLIC
public
#endif
abstract class InterceptInfo
{
public object? Tag;
Expand All @@ -59,16 +77,25 @@ abstract class InterceptInfo
public System.Collections.Generic.Dictionary<string,object?> AspectArguments;
}

#if AG_PUBLIC
public
#endif
class InterceptInfo<T> : InterceptInfo
{
public T ReturnValue;
}
}

#endif

#if !AG_NOT_GENERATE_InterceptsLocationAttribute

namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
sealed class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute
{
}
}

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// <auto-generated/>
#pragma warning disable
#nullable enable

using System;

using SR = System.Reflection;
using SLE = System.Linq.Expressions;
using SCG = System.Collections.Generic;

namespace MultiProjectAspectGenerator
{
using AspectGenerator = AspectGenerator;

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 TestMethod_Interceptor_MemberInfo = MethodOf(() => ClassLibrary.TestClass.TestMethod(default(string)));
static SCG.Dictionary<string,object?> TestMethod_Interceptor_AspectArguments_0 = new()
{
};
//
/// <summary>
/// Intercepts ClassLibrary.TestClass.TestMethod(string).
/// </summary>
//
// Intercepts ClassLibrary.TestClass.TestMethod("Test").
[System.Runtime.CompilerServices.InterceptsLocation(@"P:\AspectGenerator\Examples\MultiProject\MainApp\Program.cs", line: 12, character: 36)]
//
[System.Runtime.CompilerServices.CompilerGenerated]
//[System.Diagnostics.DebuggerStepThrough]
public static string TestMethod_Interceptor(string str)
{
// Aspects.CrossProjectAttribute
//
var __info__0 = new AspectGenerator.InterceptInfo<string>
{
MemberInfo = TestMethod_Interceptor_MemberInfo,
AspectType = typeof(Aspects.CrossProjectAttribute),
AspectArguments = TestMethod_Interceptor_AspectArguments_0,
};

__info__0.ReturnValue = ClassLibrary.TestClass.TestMethod(str);

__info__0.InterceptType = AspectGenerator.InterceptType.OnAfterCall;
Aspects.CrossProjectAttribute.OnAfterCall(__info__0);

return __info__0.ReturnValue;
}
}
}
4 changes: 2 additions & 2 deletions Examples/TransactionAspect/Aspects.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public static void OnFinally(InterceptInfo info)
{
if (info.Tag is DataConnection con)
{
if (info.Exception is null)
if (info.Exception is not null)
con.RollbackTransaction();
else
con.CommitTransaction();
Expand All @@ -73,7 +73,7 @@ public static Task OnFinallyAsync(InterceptInfo info)
{
if (info.Tag is DataConnection con)
{
return info.Exception is null
return info.Exception is not null
? con.RollbackTransactionAsync()
: con.CommitTransactionAsync();
}
Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
# Aspect Generator

[![NuGet Version and Downloads count](https://buildstats.info/nuget/AspectGenerator?includePreReleases=true)](https://www.nuget.org/packages/AspectGenerator)

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.
> [Interceptors](https://github.com/dotnet/roslyn/blob/d71ec683082104e9122a4937abc768710c5f7782/docs/features/interceptors.md) 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.

> [!WARNING]
> [!NOTE]
> The community still has doubts about the usefulness of this feature. On the one hand, it looks like not kosher fake AOP. On the other hand, it works just fine. This project can help you to try it and share your own opinion.
## Download and Install
Expand Down
2 changes: 1 addition & 1 deletion Source/AspectGenerator.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<LangVersion>preview</LangVersion>
<Nullable>enable</Nullable>

<Version>0.0.5.1-preview</Version>
<Version>0.0.5.3-preview</Version>

<IsPackage>true</IsPackage>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
Expand Down
20 changes: 19 additions & 1 deletion Source/AspectSourceGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,31 @@ namespace AspectGenerator
{
#if !AG_NOT_GENERATE_API
[Aspect]
/// <summary>
/// <para>Defines an aspect.</para>
/// <para>Create a new attribute decorated with this attribute to define an aspect.</para>
/// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
#if AG_PUBLIC
public
#endif
sealed class AspectAttribute : Attribute
{
/// <summary>
/// <para>
/// Defines method(s) name that initializes target method interception.
/// You can define multiple method overloads for different generic parameters.
/// </para>
/// <para>
/// The OnInit method should have the following signature:
/// </para>
/// <code>
/// public static InterceptInfo<T> OnInit<T>(InterceptInfo<T> info)
/// {
/// return info;
/// }
/// </code>
/// </summary>
public string? OnInit { get; set; }
public string? OnUsing { get; set; }
public string? OnUsingAsync { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,31 @@ namespace AspectGenerator
{
#if !AG_NOT_GENERATE_API

[Aspect]
/// <summary>
/// <para>Defines an aspect.</para>
/// <para>Create a new attribute decorated with this attribute to define an aspect.</para>
/// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
#if AG_PUBLIC
public
#endif
sealed class AspectAttribute : Attribute
{
/// <summary>
/// <para>
/// Defines method(s) name that initializes target method interception.
/// You can define multiple method overloads for different generic parameters.
/// </para>
/// <para>
/// The OnInit method should have the following signature:
/// </para>
/// <code>
/// public static InterceptInfo<T> OnInit<T>(InterceptInfo<T> info)
/// {
/// return info;
/// }
/// </code>
/// </summary>
public string? OnInit { get; set; }
public string? OnUsing { get; set; }
public string? OnUsingAsync { get; set; }
Expand Down
3 changes: 1 addition & 2 deletions UnitTests/Tests/Aspects.cs
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,7 @@ public static void OnAfterCall(InterceptInfo<string> info)
"string.Substring(int)"
}
)]
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
sealed class InterceptMethodsAttribute : Attribute
sealed class InterceptMethodsAttribute
{
public static void OnAfterCall(InterceptInfo<string> info)
{
Expand Down
Loading

0 comments on commit 7c59303

Please sign in to comment.