HTFramework框架使用手册(一) AspectTrack面向切面的动态调试模块

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq992817263/article/details/85617377

AspectTrack模块简介

AspectTrack模块主要是根据AOP思想架构的一个面向切面的程序代码追踪模块,它可以跟踪每一个方法的调用,在调用前阻断该方法,亦或是更改其传入的实参,更改其返回值等!可以用于调用日志打印,系统运行监控等需求!

使用AspectTrack

自定义切面代理

要使用AspectTrack,首先必须新建自定义的切面代理,切面代理必须满足以下条件:
1.继承至 AspectProxy
2.扩展接口 IAspectTrackObject
介于过程较繁琐,推荐使用快捷创建方式:
Project界面右键 -> Create -> HTFramework -> AspectProxy Script
在这里插入图片描述
如下图,我自定义了一个名为PlayerAttackProxy的切面代理,IPlayerAttackProxy接口为其代理的所有方法:

public class PlayerAttackProxy<T> : AspectProxy<T> where T : IPlayerAttackProxy
{
    public PlayerAttackProxy(T realObject) : base(realObject) { }

    public override object[] BeforeInvoke(MethodBase method, object[] args)
    {
    	GlobalTools.LogInfo("进入方法:" + method.Name);
		return args;
    }

    public override void AfterInvoke(MethodBase method, object returnValue)
    {
    	GlobalTools.LogInfo("离开方法:" + method.Name);
    }
}

public interface IPlayerAttackProxy : IAspectTrackObject
{
    void Attack(int power);
    void Hit(int hurt);
}

实现切面代理

我们新建一个类Player,使其实现IPlayerAttackProxy接口:

public class Player : MonoBehaviour, IPlayerAttackProxy
{
    int code;

    private void Awake()
    {
        code = GetHashCode();
    }

    public void Attack(int power)
    {
        GlobalTools.LogInfo(code + " 攻击:[攻击力 " + power + "]");
    }

    public void Hit(int hurt)
    {
        GlobalTools.LogInfo(code + " 被击:[伤害 " + hurt + "]");
    }

    public void Track()
    {
        GlobalTools.LogInfo(" 追踪目标:" + GetType().Name + " " + code);
    }
    
    private void Start()
    {
        Attack(100);
        Hit(50);
        Track();
    }
}

常规调用

然后我们在编辑器中挂载Player脚本,运行!结果如我们所料:
在这里插入图片描述

切面代理调用

接下来我们想要对PlayerAttack方法和Hit方法进行追踪,当然这也是我们一开始的初衷,修改Player类的Start方法:

    private void Start()
    {
        //创建切面代理
        PlayerAttackProxy<IPlayerAttackProxy> proxy = new PlayerAttackProxy<IPlayerAttackProxy>(this);
        //创建追踪者
        IPlayerAttackProxy proxyObj = Main.m_AspectTrack.CreateTracker(proxy);

        proxyObj.Attack(100);
        proxyObj.Hit(50);
        proxyObj.Track();
    }

然后我们在编辑器中挂载Player脚本,运行!结果如我们所料:
在这里插入图片描述
如你所见,Player中的Attack方法和Hit方法,每次调用都将会被PlayerAttackProxy捕获到,BeforeInvoke将于方法正式调用前被呼叫,AfterInvoke将于方法正式调用后被呼叫。

修改方法实参

想要修改方法调用时传入的实参,只需修改BeforeInvoke传入的参数并传出便可:

    public override object[] BeforeInvoke(MethodBase method, object[] args)
    {
        GlobalTools.LogInfo("进入方法:" + method.Name);
		//将所有int数据放大到10000
        for (int i = 0; i < args.Length; i++)
        {
            if (args[i] is int)
            {
                args[i] = 10000;
            }
        }

		return args;
    }

运行!
在这里插入图片描述

获取方法返回值

方法的返回值可以从AfterInvoke中获取:

    public override void AfterInvoke(MethodBase method, object returnValue)
    {
        GlobalTools.LogInfo("离开方法:" + method.Name);
        GlobalTools.LogInfo("方法:" + method.Name + " 返回值 " + (returnValue == null ? "null" : returnValue.ToString()));
    }

运行!
在这里插入图片描述

拦截方法调用

PlayerAttackProxyInterceptCall字段决定了方法是否被拦截,不过需要注意的是,这里只能拦截void返回值的方法,如若方法有非空返回值,那么拦截了它的调用之后,将不太好处理之后引发的一系列麻烦:

    private void Start()
    {
        //创建切面代理
        PlayerAttackProxy<IPlayerAttackProxy> proxy = new PlayerAttackProxy<IPlayerAttackProxy>(this);
        IPlayerAttackProxy proxyObj = Main.m_AspectTrack.CreateTracker(proxy);

        //拦截所有void返回值方法的调用
        proxy.InterceptCall = true;

        proxyObj.Attack(100);
        proxyObj.Hit(50);
        proxyObj.Track();
    }

运行!
在这里插入图片描述

启用与禁用切面代理模块

AspectTrack将可以很方便的调试某些复杂模块,或者完成某些重复性高的统一功能,这将取决于你如何使用它,不过,使用它的代价并不低,如果想要在正式发布的项目中去掉整个切面代理的功能,不需要改动任何代码,只需要一句话关闭它就可以了!

Main.m_AspectTrack.IsEnableAspectTrack = false;

猜你喜欢

转载自blog.csdn.net/qq992817263/article/details/85617377