New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: Custom attribute for Pre-compile AOP #59454
Comments
I think it's probably better to at least sketch how this should be implemented. For example, I can't figure out how async interceptor methods can be applied on sync methods. Another problem is that this might be too complicated and specific to be a pure runtime feature. It might be better to propose that the runtime only exposes a more general API (for example, to raise an event that allows the program to modify the IL of a method while it is loaded), which the C# compiler can use to make this happen. Again, I think it is necessary to provide more information on how this should be designed and implemented. I also want to remind you that C# team are known to have negative attitudes toward AOP. That's why there are so many third-party tools in this area. |
I am not compiler expert. There is a Java IDE plugin called Lombok which can decorate Java code before real compile. I think that would be a good reference. Sync methods use sync interceptor. Async method use async interceptor. This is why AopAttribute need both sync and async implementation.
I suppose this AopAttribute may be supported in
Yeah, more or less I know that. But AOP is a big area and have many types. |
Why not use something like https://github.com/vescon/MethodBoundaryAspect.Fody |
Three reasons:
Edited: MethodBoundaryAspect.Fody can support async method, but itself do not have async version. |
I'm pretty sure we're not going to build AOP into the runtime. Everyone would prefer everything to be built into the runtime even though they are packages on nuget that can do similar things. |
I agree that the runetime should not combine with
But some kine of |
MethodBoundaryAspect.Fody can support async method, but the
Sorry my bad, seems like it uses |
Another reason to avoid Fody related stuff is its strange License. Actually I think the C# source generator can be a good replacement to Fody in many cases. For example, the async interception can be designed as: //Ask the source generator to generate a method with name "YourPublicMethod"
[GenerateInterceptedMethod("YourPublicMethod")]
[Log] //Add anything you want as attributes here.
private async Task YourImplementation() //The name of this method is only used by the source generator.
{
//Actual implementation.
} Then the generator will generate: public async Task YourPublicMethod()
{
await Log.BeforeMethod(...);
await YourImplementation();
await Log.AfterMethod(...);
} |
Yes! Some kind of source code generator before |
Source generator is very versatile. The only issue is that it's still new and you probably have to write your own generator for your specific task, including something like this AOP feature. |
This is why I proposal a |
Source generators won't help you as they can't change the call site. You can experiment with them anyways because this issue isn't something we plan to do |
You don't need to. The actual implementation can be another private method, while all call sites use the generated, public one. |
The problem with integrating this into the runtime is that only very few apps can benefit from it. In this case, a third-party library might be a better way to go. |
As mentioned in MethodBoundaryAspect.Fody, with AOP:
Transaction ,logging, caching, is very common in daily programming. |
Maybe AOP is not a good name for this issue. |
Found one another possible alternative https://github.com/pamidur/aspect-injector |
I strongly against third-party |
I'd much rather continuing to lobby the C# team to make source generators handle AOP scenarios better. Generators themselves might be more difficult to write, but theoretically you could write a general purpose generator that would recognize attributes that follow a specific convention (or implement an interface) and have that generator emit the code to call into those attributes, which would behave similarly to what you've proposed here. |
I don't know how you'd build this with what source generators offer today but here's something roslyn based https://github.com/Jishun/RoslynWeave |
He is trying to achieve the same goal. He use source code template to create a new wrapper class in another namespace, then all caller need to change their code to call the new class. I guess there should already be some code-gen that support code-rewriting, inside or outside compiler. using (var conn = new Connection())
{
} rewrited to Connection conn;
try
{
conn = new Connection()
}
finally
{
conn.Dispose();
} So I am thinking if such code-gen can do another similiar rewrite: [MyPerfLog()]
public bool Login(string userName, string password)
{
//check with db
return true;
} rewrite to: public bool Login(string userName, string password)
{
MyPerfLog.BeforeMethod();
var resultInfo = Login_juedhrygjddhdgd(userName, password);
MyPerfLog.AfterMethod();
}
public bool Login_juedhrygjddhdgd(string userName, string password)
{
//check with db
return true;
} If such |
Maybe JSR 269 Pluggable Annotation Processing API is what we need. |
https://github.com/postsharp/Metalama |
https://github.com/dotnet/roslyn/blob/main/docs/features/interceptors.md This looks like what I had wanted. |
Background and motivation
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
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
Then the compiler will take care the rest.
Risks
Alternative
The text was updated successfully, but these errors were encountered: