This project is read-only.

Can I use Roslyn as a static aspect weaver?

Topics: APIs
Apr 9, 2014 at 8:58 AM
Edited Apr 9, 2014 at 9:10 AM
I would like to generate extra code in the resulting assembly (NOT the source files) triggered by the presence of a code attribute. An intermediate source file that is compiled instead of the original would also work (and be great for debugging).
[InjectSomeCodeAspect]
public void MyMethod(string name)
{
    Console.WriteLine("Hello " + name);
}
would result in something like:
public void MyMethod(string name)
{
    var aspect = InjectSomeCodeAspect.GetAspect();

    using(var interceptor = aspect.CreateInterceptor())
    {
        var ctx = new InterceptionContext(MyMethod_Internal, this);
        ctx.AddParameter(() => name);

        interceptor.Execute(ctx);
    }
}

// original method - made private
private void MyMethod_Internal(string name)
{
    Console.WriteLine("Hello " + name);
}
This would allow anyone to intercept method execution controlled by simple declarative code attributes.

Question is: Is this possible?
If so, can you point me in the right direction?

Thanx very much,
Marc Jacobi
Apr 9, 2014 at 11:12 AM
Marc,

Yes, but it's incredibly ugly right now.

I'm writing a different tool that takes a more complex alternate source and replaces it in the source code set. That's not a change to the original file, it's never actually compiled, just use to create the file that is compiled. I'm walking down this route because it leaves "real" code for debugging.

You're calling this an aspect weaver, but I believe Roslyn makes the line between AOP and embedded DSL pretty vague. And the only difference between that and generation is whether you create source artifacts or IL artifacts. This commonality means that there is one core thing to do and three ways we've traditionally thought about the problem. One core, three implementations, or we start doing a single thing with source/IL flavors. (I group all these things under metadata).

So, if you explore this, I really look forward to your comments. This morning I threw out the majority of stuff I've done on this more complex problem (I have a simple approach to code first metadata extraction from any source into any logical structure that I'm just tidying up for release). I threw that work out because the Roslyn tree is very difficult to approach with generalizations. A class can have three different parents, they share no commonality (interface or base) and everything is sealed. Add the many variations (qualified name, etc), and something as simple as getting the name of something is a method with about 15 branches (no, I didn't write it that way, but that's still the logic). I want to hear if you have a different experience.

Roslyn is not designed for metaprogramming. This is a good thing. It's designed as a compiler. In two years I hope we have a metadata/Roslyn friendly thing (I can think of a few implementations) from MS or more likely OSS. The nice thing about OSS is that it can be a component that can work with Roslyn or anything else via a shim layer. You are one of the people I'd like to see input to that, at least intellectual if not effort.

But none of that helps you right now. I don't have a sample to point you to on this. It's different enough from what I'm doing (and now implementing a new design on) that I don't think it would help. My suggestion is to cruise the FAQ in the samples. That will help you grok the overall. Find the source reference tool if you haven’t. Then create the code block as an isolated exercise – finding and using the Roslyn quoter as a starting point. I suspect you grok DOM and therefore the deep nesting and complexity from having everything immutable, sealed won’t be an issue. Along the way you’ll have to get symbol names (remember they may be qualified), work with the parent (only two types in this case), and alter the tree – which means building a new one with “With” and “Add” (both are immutable) and replacing the entire compilation unit. Start with the sample here or simpler – but keep in mind you may have parameters in a future attribute. Structured trivia is your friend and annotations a good beer buddy, although you may need neither for this task.

It would be totally awesome if you could release a generalized attribute weaver. If the work I am doing today pans out, I may have a way to create the code to insert that is an alternative manual creation of tree creation (or a manual variation of Roslyn weaver output), but that’s just one part of you are doing.

I’m explaining the direction I’m headed in hopes that folks work together to create the first version of a handful of tools we really want for Roslyn. Accessing the internals of Roslyn is very ugly and I’m hoping we can work together to create some wrappers that simplify future efforts, but I don’t know if needs will align.

BTW, for future readers. Note that I am writing this post April 9, 2014 when this stuff is very new and dynamic. This post may become out of date very quickly.

Kathleen
Apr 9, 2014 at 2:35 PM
Wow Kathleen, what an elaborate answer! I really appreciate that, thank you so much.

I was hoping to get a quick fix but it seems I need to put in a lot more time. Currently I am trying to get an Windows-store app of the ground so I guess it has to wait a bit. But meanwhile I will try to get more familiar with the Roslyn design and APIs. I will start with the FAQs.

Hope to resume the discussion at a later time.
Marc
Aug 21, 2014 at 7:09 PM
Is there any update on this subject?

Thanks,
Ramesh