postsharp / Metalama

Metalama is a Roslyn-based meta-programming framework. Use this repo to report bugs or ask questions.
164 stars 4 forks source link

Feature request: Specify aspect order with explicit Before or After instead of full order #192

Closed WhitWaldo closed 11 months ago

WhitWaldo commented 11 months ago

Today, aspects can be applied in order either by type or by namespace. I currently keep each of my aspects in a separate project (and the fabrics in separate projects from those too) so I can explicitly apply the aspect per-entity or apply the fabric on a case-by-case basis without opting into everything at once.

Because I've been creating more and more aspects, it's becoming difficult to specify the order of child aspects in some of the consuming projects since I have to specify the entire intended order when the aspect is consumed instead of only the aspects I'm directly consuming in the project.

I'd like to request that the order mechanism be re-imagined so that instead of having to specify the order of all the aspects all at once in the downstream assembly (and having to, there, know all the aspects being applied, whether as children or not), I'd instead love to be able to specify the order by indicating the namespaces or types of all the aspects that should explicitly precede or succeed the given aspect. At compile time, a graph should be constructed of each of the explicit constraints to determine order. If an order isn't specified, Metalama should automatically handle the ordering however you want to do it.

This way, within a project A with parent and child aspects, I can specify directly in that project what the ordering should be. But in any other project B consuming this project A, I need only indicate the ordering with regards to the aspect intended to be consumed by the others.

Further, it means I can specify the order of aspects that I'm not explicitly including in that project, but which I can articulate an "optional" dependency on in case they are ever included elsewhere.

Thank you for the consideration!

PostSharpBot commented 11 months ago

Hello @WhitWaldo, thank you for submitting this issue. We will try to get back to you as soon as possible. Note to the PostSharp team, this ticket is being tracked in our dashboard under ID TP-33585.

svick commented 11 months ago

I'd instead love to be able to specify the order by indicating the [...] types of all the aspects that should explicitly precede or succeed the given aspect

As explained in the documentation, you pretty much already can do that. For example, if you want to specify that aspects Before1 and Before2 are in the execution order before aspect MainAspect, you can do it like this:

[assembly: AspectOrder( typeof(Before1), typeof(MainAspect) )]
[assembly: AspectOrder( typeof(Before2), typeof(MainAspect) )]

I can specify the order of aspects that I'm not explicitly including in that project, but which I can articulate an "optional" dependency on in case they are ever included elsewhere

I believe you should be able to do that using the string overload of AspectOrder.

WhitWaldo commented 11 months ago

Yes, but the larger idea here is that I might have aspect A and aspect B in some project, one intended to be a child aspect of the other, but not necessarily used outside of the project. If I then use aspect A in another project, I'm going to have to know about aspect B when I set up the ordering because there's no.. "relative" ordering. I have to be fully explicit about the order of all the aspects and their application.

Thus this ask - I'd like to be able to specify the intended order of aspect application locally without having downstream projects know anything about "child" aspects that serve only as utilities within larger aspect implementations.

For a more concrete example.. I have a project A that implements a RepositoryAspect and an IndexAspect. Index has a dependency on Repository and I'd like to be able to indicate that in the project locally. I have a separate project B that implements a LoggingAspect. In a downstream project C, I'd like to have the option to implement Logging and Repository or Index as the case may be. What I'd like to be able to do is indicate in project A that Repository should be applied before Index and that if it's applied, Logging should always come last. In project C then, where I might have still other aspects applied, I'd like to simply say that the other aspects should be applied before either Repository or Index, whichever one I'm using and have Metalama automatically work out that without be explicitly saying it in project C that Logging will always be applied last (as configured explicitly in project A).

Today, I'm not aware this is possible without project C being fully aware of all possible aspects referenced and used and setting one specific and comprehensive order for all of them.

svick commented 11 months ago

If you specify some aspects and their AspectOrders in project A, then a project referencing it doesn't have to repeat that. Metalama takes all the known ordering constraints into account and figures out the final order based on those.

So, if you have in project A:

[assembly: AspectOrder(typeof(Repository), typeof(Index))]
[assembly: AspectOrder("A.Index", "B.Logging")]

And in project C:

[assembly: AspectOrder(typeof(StillOtherAspect), typeof(Repository))]

Then it should work the way you want.