Open
Description
Background and motivation
[MyCache(DurationSeconds = 5)]
public string GetUserName(int userID)
{
//load from db
return "Mike";
}
[MyPerfLog()]
public bool Login(string userName, string password)
{
//check with db
return true;
}
It is very annoying to add AOP to functions.
For now, you need to:
1, Create a custom Attribute
2, Create a custom Interceptor to handle your custom Attribute
3, Register your Interceptor at application startup
I think there would be a syntactic sugar
that handling specific attribute.
API Proposal
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public abstract class AopAttribute : Attribute
{
/// <summary>
/// </summary>
/// <returns>if execute the real Method or not</returns>
public abstract bool BeforeMethod(MethodInfo info);
public abstract void AfterMethod(ResultInfo result);
public abstract Task<bool> BeforeMethodAsync(MethodInfo info);
public abstract Task AfterMethodAsync(ResultInfo result);
}
This is a compile-time attribute, more or less like System.Diagnostics.ConditionalAttribute
.
Compiler will generate proxy class to wrap the target functions.
API Usage
public class MyPerfLogAttribute : AopAttribute
{
ILogger _logger;
DateTime _begin;
public MyPerfLogAttribute(ILogger logger)
{
_logger = logger;
}
public override bool BeforeMethod(MethodInfo info)
{
_begin = DateTime.Now;
return true;
}
public override async Task<bool> BeforeMethodAsync(MethodInfo info)
{
_begin = DateTime.Now;
await Task.CompletedTask;
return true;
}
public override void AfterMethod(ResultInfo result)
{
var span = DateTime.Now - _begin;
_logger.LogInformation($"use {span.TotalMilliseconds:0.00}");
}
public override async Task AfterMethodAsync(ResultInfo result)
{
var span = DateTime.Now - _begin;
_logger.LogInformation($"use {span.TotalMilliseconds:0.00}");
await Task.CompletedTask;
}
}
[MyPerfLog()]
public bool Login(string userName, string password)
{
//check with db
return true;
}
Then the compiler will take care the rest.
Risks
- Application Performance: should not be affected.
- Compiler complexity: should be fine.
- Extensibility: should be fine.
- Applicability: AOP is a very common requirement. Such compiler supported pre-compile AOP attribute should be very sweet.
Alternative
- A built-in interceptor can also do such things easily. A built-in interceptor will not need to change compiler, but will slow down the application startup speed. Application startup speed is important in this docker(container) era.