K, reopened for Carlo to have a look at tomorrow.
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
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.
Yes, it works!
This was exactly what I meant with my request.
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
I have two:
- A method insert-point where the aspect can insert code into the original body.
- 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.