Selective compilation

Technical questions about PostSharp Laos.

Selective compilation

Postby bmorley on Tue Apr 08, 2008 6:45 am

One of the things that came up while reviewing AOP using Laos is the potential for determine at compile time which code to compile as your aspect for a specific object. Perhaps I am missing something, but this is how I picture the aspect being applied in my little head.

[MyAspect]
MethodOne() {
}

[MyAspect]
MethodTwo() {
}

At compile time MyAspect would go through compile-time validation twice (once for each method) and would be compiled twice (and serialized?) for each method (understanding at least at some level, that this is done against the MSIL for the assembly).

My question is could I do something like this in "MyAspect" ...

public override bool CompileTimevalidation(MethodBase method) {
if (my method is fancy) {
#define FANCY_TRACE
} else {
#undef FANCY_TRACE
}
}

public override void OnEntry(MethodExecutionEventArgs eventArgs) {
#if FANCY_TRACE
DoMyFancyTracing();
#else
DoMyBoringTracing();
#endif
}

I suspect the trouble with this approach is that the compiler flags I have used are precompiler directives and as a result, can not be programatically defined. Is there another technique we could apply to achieve this? The hope here is to be able to produce an OnEntry method that has to do the minimum amount of logic checks (mostly for performance reasons). The idea here is that the aspect can determine if the method it is being applied to is "fancy" or not. Certainly a boolean on the aspect and a simple check in the OnEntry is very trivial, but I suspect we could come up with some examples where the run-time code has to do extra work that is significant and would not have to be coded if the functionality was simply built into the method the aspect was being applied to.
bmorley
 
Posts: 8
Joined: Tue Apr 08, 2008 6:08 am
Full Name: Bob Morley
Company: Software Innovation

Re: Selective compilation

Postby gfraiteur on Tue Apr 08, 2008 10:54 am

Hi,

There is no real support for conditional compilation, but you have the choice between the following strategies:

1. You can define your aspect as a CompoundAspect and provide the real aspect implementation conditionally to an assembly-level custom attribute whose presence or value depends on a compilation symbol (for instance AssemblyConfigurationAttribute).

2. You can do something similar at runtime: in the static constructor of your aspect, check the presence of some configuration parameter or custom attribute and store the flag as a static field. Then, in OnEntry, execute the logic conditionally to this flag.

I hope this helped.

Gael
Gael Fraiteur, project leader
got good support? consider donating to the project.
gfraiteur
Site Admin
 
Posts: 673
Joined: Tue Dec 18, 2007 3:09 pm
Full Name: Gael Fraiteur
Company: postsharp.org

Re: Selective compilation

Postby Lance on Wed Apr 09, 2008 1:54 pm

Hi,
Gael - Do you have any examples of how to implement 1)? I don't really understand your response and a brief example would help.


I too think it would be nice to have a way to alter the use of the Attribute during runtime.


I'm using PostSharp in an ASP.NET application to trace the Thread path and write to logs and Trace. Currently I'm just commenting out the Attributes to avoid having either the post-compile job bloating the code, and thereby stopping the Tracing from working. It's a bit of one hammer to do both jobs.

Here's what I'm doing to stop Tracing for release:

#if DEBUG
[assembly: EasyTrace]
#endif

But that stops both the post-compile job from running AND the Trace.

It's not going to be a very busy application, so it would be OK to leave the Tracing in the Release code, as long as I could turn it off so it's not doing tonnes of logging in the Production environment.

Since I'm using the Attribute at the Assembly level, method 2) it a bit difficult to use. I'd like to just read a flag value out of the web.config at runtime, but since the method that reads the value itself has the logging Attribute applied against it (as it's part of the Assembly), I get into an *evil* recursive process of flag-fetching that results in an out-of memory exception.

Of course I *could* use the old [EasyTrace(null, AttributeExclude = true)] on the Config.GetConfigValue method, but I actually want to see when this gets called during the Application execution.

Also of course I *could* roll my own alternate method to fetch the flag that's not using the logging Attribute - but that feels a bit hackey.

It would be GREAT to be able to use a web.config flag to turn off the call to the Attribute - so that the EasyTrace (see below) class isn't even called for assemblies and classes that are decorated with it. Rather that what I've tried, sniffing for the Flag *inside* of each of the EasyTrace methods.


Code: Select all
    [EasyTrace(null, AttributeExclude = true)]
    [Serializable]
    public class EasyTrace : OnMethodBoundaryAspect
    {
...


       public string TraceLevel
        {
            get
            {
                if (null == _traceLevel)
                {
                    string t = Config.GetConfigValue("trace_level"); //this goes to the method which triggers the OnEntry
                    _traceLevel = t;
                   }
                return _traceLevel;
            }
        }
...

       public override void OnEntry(MethodExecutionEventArgs eventArgs)
        {
            if ("Trace" == TraceLevel) //goes to fetch the TraceLevel property
            {
                string s = string.Format("Entering {2}.{0}.{1}.",
                                   eventArgs.Method.DeclaringType.Name,
                                   eventArgs.Method.Name,
                                   eventArgs.Method.Module);


                ParameterInfo[] pi = eventArgs.Method.GetParameters();
                if (pi.Length > 0)
                {
                    s += " ARGUMENTS:(";
                    for (int x = 0; x < pi.Length; x++)
                    {
                        s += String.Format("{0} - {1}: ", pi[x].Name, pi[x].ParameterType);
                    }
                    s += ")";
                }


                Utility.Log(s);
                WriteTrace(s);
            }
        }
...




Thanks,
Lance
PS - I only found out about AOP yesterday, so please be gentle!
Lance
 
Posts: 2
Joined: Wed Apr 09, 2008 12:14 pm
Full Name: Lance

Re: Selective compilation

Postby gfraiteur on Wed Apr 09, 2008 3:48 pm

Lance wrote:Hi,
Gael - Do you have any examples of how to implement 1)? I don't really understand your response and a brief example would help.


The sample PostSharp.Samples.Binding uses type-level CompoundAspect. Another complex project based on assembly-level CompoundAspect is PostSharp4EntLib, but you will probably find it difficult to analyze.


Currently I'm just commenting out the Attributes to avoid having either the post-compile job bloating the code, and thereby stopping the Tracing from working. It's a bit of one hammer to do both jobs.


Couldn't you apply the ConditionalAttribute to your aspect, so that the C# compiler emits the custom attribute only if a defined compilation symbol is applied?
Gael Fraiteur, project leader
got good support? consider donating to the project.
gfraiteur
Site Admin
 
Posts: 673
Joined: Tue Dec 18, 2007 3:09 pm
Full Name: Gael Fraiteur
Company: postsharp.org


Return to PostSharp Laos


cron