Feature request: simpler programming of aspects

K, reopened for Carlo to have a look at tomorrow.

1 Like

what am I missing?

this looks fine?

Strange, just tried in the test project and it is working, tried yesterday in the operational project, where it did not work.

I am going to investigate what the difference is.

I don’t know what the problem is, but in my real project it does not work.
The project:

To reproduce: rebuild the dll BuildITClasses.
The file buildITStrings.pas has the aspect in it, the aspect is defined in buildITAspects.dll, file ExtensionFields.pas

Thanks, logged as bugs://83013

Just thought of the difference.
In the test project, the HandleInterface method was doing nothing.
In the real project, this was doing a lot.

But if I remove the code from the handleInterface method in the real project, the compile hangs on:
-> Phase Checking Members started.

So I found this; it’s actually caused by removing the field. That makes it not trigger the “implement body for this method” because it’s tied to the other side of the field. But this makes it a bit of a “hard” problem.

If you add:


  (self as IAutoGenMethodImplementationDecorator).AutoGenHandleImplementation(services, aField.Owner);

to the bottom of the method, it should work.

I’ve also reproduced the deadlock and pushed a fix for that.

1 Like

bugs://83013 got closed with status fixed.

bugs://83004 got closed with status fixed.

Yes, it works!

This was exactly what I meant with my request.

1 Like

Carlo,
I now replaced the test code with the real code, and I get:

Exception while applying aspect “builditAspects.ExtensionField”: Value cannot be null.
Parameter name: Code

The code of the aspect (I removed everything else for test):

type
    [AttributeUsage(AttributeTargets.Field)]
    ExtensionField = public class(Attribute, IFieldInterfaceDecorator)
public
    method HandleInterface(Services: IServices; aField: IFieldDefinition);
    begin
        // do nothing, removed for injection test
    end;
    [AutoInjectIntoTarget]
    class method Set_Field_Value(key: Object; val: Object; Dictionary: System.Collections.Generic.Dictionary<WeakReference, Object>);
    begin
        //var WeakKey :=  GetKeyOnTarget(key, Dictionary);
        var WeakKey : System.WeakReference := nil;
        For each k: System.WeakReference in Dictionary.Keys.ToArray do
        begin
            if k.Target = key then
            begin
                WeakKey := k;
                break;
            end
            else if k.Target = nil then                                      
                Dictionary.Remove(k);
        end;

        if WeakKey <> nil then
            Dictionary[WeakKey] := val
        else if val <> nil then
            Dictionary.Add(new WeakReference(key), val)
        else
            Dictionary.Remove(WeakKey);
    end;
end;

hrmm. Just tried this:

namespace builditAspects;

interface

uses 
  System.Linq,
  RemObjects.Elements.Cirrus.*;

type
    [AttributeUsage(AttributeTargets.Field)]
    ExtensionField = public class(Attribute, IFieldInterfaceDecorator)
private
public
    method HandleInterface(Services: IServices; aField: IFieldDefinition);
    begin
    
    end;

    
[AutoInjectIntoTarget]
    class method Set_Field_Value(key: Object; val: Object; Dictionary: System.Collections.Generic.Dictionary<WeakReference, Object>);
    begin
        //var WeakKey :=  GetKeyOnTarget(key, Dictionary);
        var WeakKey : System.WeakReference := nil;
        For each k: System.WeakReference in Dictionary.Keys.ToArray do
        begin
            if k.Target = key then
            begin
                WeakKey := k;
                break;
            end
            else if k.Target = nil then                                      
                Dictionary.Remove(k);
        end;

        if WeakKey <> nil then
            Dictionary[WeakKey] := val
        else if val <> nil then
            Dictionary.Add(new WeakReference(key), val)
        else
            Dictionary.Remove(WeakKey);
    end;

end;

implementation


end.

But it compiles builditAspects & BuildItClasses just fine. What am I missing?

Send you a new test project by PM

1 Like

I have two:

  1. A method insert-point where the aspect can insert code into the original body.
  2. A IMethodDefinition.RemoveLocal function

example usage:

method x;
begin
    //some code
    [InsertCodeAspect]
   //some code
end;

This makes it possible to implement things like the static fields with aspects; that would look like:

method x;
begin
    [StaticAspect]
    var MyStaticVar: Integer;
    //some code
end;

In this example the implementation of the StaticAspect will remove the variable and add the code to implement the static at the insertion point.