Unity AOP also known as Unity Aspect Oriented Programming is a framework for Unity3D that allows to use aspects in your games. It uses Mono.Cecil to rewrite compiled assembly basing on aspect attributes.
public class MyCustomAspect : Attribute, IMethodEnterAspect
{
public void OnMethodEnter(MethodExecutionArguments args)
{
Debug.Log("Hello my dear method named '" + args.method.Name + "'");
}
}
- Not tested on: iOS, OSX, Linux (but it should work...)
You can use Aspect Attributes such as following:
IMethodEnterAspect
- executed when method is enteredIMethodExitAspect
- executed before method returns value to source of invocationIMethodExceptionThrownAspect
- executed when method throws an exception during executionIMethodBoundaryAspect
- combo forIMethodEnterAspect
andIMethodExitAspect
IPropertyGetEnterAspect
- executed when get method of property begins to be invokedIPropertyGetExitAspect
- executed when get method of property finishes its invocationIPropertySetEnterAspect
- executed when set method of property begins to be invokedIPropertySetExitAspect
- executed when set method of property finishes its invocationIPropertyExceptionThrownAspect
- executed when property throws an exception
IBeforeEventInvokedAspect
- executed before event is invokedIAfterEventInvokedAspect
- executed after event is invoked- ...InvokedAspect does not contain event arguments!
IEventBeforeListenerAddedAspect
- executed before listener is added to eventIEventAfterListenerAddedAspect
- executed after listener is added to eventIEventBeforeListenerRemovedAspect
- executed before listener is removed from eventIEventAfterListenerRemovedAspect
- executed after listener is removed from eventIEventExceptionThrownAspect
- executed when event throws exception (excluding invocation)
It's simple.
- Create new class
- Inherit from Attribute
- Add desired interfaces
- Implement methods
- Profit
It's recommended to use [AttributeUsage] on aspects to limit it to proper members.
Yes, you should use Variables. All arguments used in Aspects inherit BaseExecutionArgs. Inside you've methods:
AddVariable(string name, object value)
- which adds variable to local memory of aspect callGetVariable<T>(string name)
- which gets variable using name, if none returns default
Yes, you can. Just use args.Throw(<System.Exception>);
and you're fine. It is recommended to use return
after this method, otherwise the Aspect code will continue to execute.
No, you can't, however you can encapsulate field into Property which is supported - it is less painful solution both for you and your processor :) An example:
[Serializable]
public class Foo
{
[SerializeField]
private string name;
public string Name { get => name; [Observable] set => name = value; }
}
public class ObservableAttribute : Attribute, IMethodEnterAspect
{
public void OnMethodEnter(MethodExecutionArguments args)
{
args.Throw(new Exception("Hello world! Breaking things is fun!"));
return;
Debug.Log("Foo has been set");
}
}
Yes, just implement all interfaces you desire :)
It's MIT licensed. Feel free to commit updated versions into Git. Feel free to send me a link, so I could implement your upgrades too.
494311870 - build compatibility (including Android), because I was too lazy to fix this...
blazejhanzel - multi-DLL weaving implementation