Skip to content
This repository has been archived by the owner on Jul 12, 2023. It is now read-only.

Can I make aspect on Field setted? #1

Closed
xzaxzaazx opened this issue Jan 16, 2021 · 2 comments
Closed

Can I make aspect on Field setted? #1

xzaxzaazx opened this issue Jan 16, 2021 · 2 comments

Comments

@xzaxzaazx
Copy link

xzaxzaazx commented Jan 16, 2021

I'm considering such a attribute feature like this:

public class Foo{
   [Observable]public string name;
}
public class FooObserver{
   void LinkFoo(Foo foo){
      foo.name.AddListener((oldvalue,newvalue)=>{
         //Do Something;
      })
   }
}

but I need a OnFieldSetted aspect, is it possible?

@H1M4W4R1
Copy link
Owner

H1M4W4R1 commented Jan 21, 2021

Yes it's possible to create such aspect, but it would require to create additional modifications inside Aspect Processing. The generic problem is that Fields are not considered methods (which are supported atm.), so you need to scan all methods on all types in all assemblies in project and update field set method to implement similar event. It's really complicated...

From the exact point of view the UAOP copies the method body into new method and replaces old method with new body that executes wrapper which later uses System.Reflection to invoke copied method (you can check assemblies using decompiler like DotPeek). This is not possible in fields, because field uses stfld stsfld ldfld and ldfld IL codes, which are not call/callvirt for methods (like Properties or Events).

SOLUTION:
Alternative solution is to wrap the field like this:

public class Foo {
   private string name;
   public string Name { get; [Observable] set; }
}

And then use [Observable] with OnMethodEnter/Exit Aspects, because set_Name is an method that is created by compiler during runtime so it can be modified by UAOP. This is the best solution rather than scanning all method bodies in all types ;)

@H1M4W4R1
Copy link
Owner

H1M4W4R1 commented Jan 21, 2021

So your code should look like this:

public class Foo
{
    public string Name { get; [Observable] set; }
}

public class ObservableAttribute : Attribute, IMethodEnterAspect
{
    public void OnMethodEnter(MethodExecutionArguments args)
    {
        Debug.Log("Foo has been set");
    }
}

Beware: this excutes BEFORE method name is changed. If you want to execute it AFTER, you need to use IMethodExitAspect with OnMethodExit implementable.

Verification in Unity:
image

@H1M4W4R1 H1M4W4R1 pinned this issue Jan 21, 2021
H1M4W4R1 pushed a commit that referenced this issue Jun 8, 2023
…support

Added support for multiple dll files injection
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants