How do I weave C # code to intercept the call to constructors? Maybe a custom preprocessor or Roslyn

Is there any solution like [PostSharp] - [Infuse - Precompiler for C #] that allows me to modify the code at compile time?

Below is the pseudocode.

[InterceptCallToConstructors]
void Method1(){
    Person Eric = new Person("Eric Bush");
}


InterceptCallToConstructors(ConstructorMethodArgs args){
    if(args.Type == typeof(Person))
        if(PersonInstances++ > 10 ) args.ReturnValue = null;
}

      

In this example, we can see that Eric should not contain a new Person class if more than 10 people are created.

After some research, I found two solutions PostSharp and Infuse. Infuse makes it very difficult and tricky to determine how many Person instances were made when PostScriptSparp contains a single discoverable string code.

I tried to run AOP with PostSharp, but PostSharp does not currently support intercepting Call To Constructor Aspect.
As far as I understand, Roslyn does not support compile-time code changes.

+3


source to share


2 answers


This will be a "custom preprocessor" response that modifies the source code to achieve the OP's effect.

Our DMS Software Reengineering Toolkit with its C # Front End can do this.

DMS provides source-to-source transformations, with transformations encoded as

if you see *this*, replace it by *that*

      

This is written in the form:

rule xxx pattern_parameters
    this_pattern
    ->  that_pattern ;

      

"->" pronounced "replace by :: -}



DMS runs on AST, so it includes a parsing step (text to AST), a tree transformation step, and a pretty print step that gives the final answer (ASTs to text).

It seems the OP wants to change the site of the constructor invocation (he cannot change the constructor, there is no way to make it return "null"). To accomplish the OP's task, he provided the DMS with the following source-to-source conversion specification:

       default domain CSharp~v5;  -- says we are working with C# syntax (and need the C# front end)

       rule intercept_constructor(c: IDENTIFIER, a:arguments): expression
           "  new \c (\a) "
       ->  "  \c.PersonInstances==10?null:(PersonInstances++,new \c (\a)) "
           if c == "Person";  -- one might want to force c to be on some qualified path

      

What the rule does is find the syntax for calling a constructor for an arbitrary form and replace it with a conditional that checks the OP's precondition, returning null if there are too many Person instances (we'll fix a bug in the OP spec here, it appears to increment the counter, is created whether a new Person instance or not is of course not its intention). We have to qualify the location of PersonInstance; he cannot just float on the air. For this example, I suggest that it is a static member of the class.

Details: each rule has a name ("intercept_constructor" stolen from the OP). It belongs to the syntactic category ("expression") with the syntactic form "new \ c (\ a)", causing it to only respond to constructor calls that are expressions. The quotes in the rule are meta quotes; they distinguish the syntax of the rule language from the syntax of the target language (in this case, C #). Backslashes are meta-screens; \ c in meta-quotes thinks the same in a rule as c outside meta-quotes, similar to \ a.

In a really large system, there may be multiple Person classes. We want to make sure we get the right one; you might need to qualify the referenced class as specific by providing a path. The OP hints at this with an annotation. If someone wanted to check that there is an annotation contained in an addition method, this would require a special special predicate. The DMS provides complete coding capabilities for such a predicate, including full access to the AST, so the predicate can climb up or down in search of a suitable annotation.

+1


source


If you are working on top of KRuntime (-> ASP.NET 5), you can hook into compilation by implementing the ICompileModule neutral assembly interface .

I would recommend loooking at:



0


source







All Articles