消息机制的优化----------无需进行装箱/拆箱的  版本

http://www.manew.com/thread-111056-1-1.html

 

 

装箱/拆箱为了解释“为什么不用object传递参数?”先简单介绍一下“装箱/拆箱”,请看下面代码:

[C#] 纯文本查看 复制代码

int a = 10;

object b = a; //装箱

a = (int)b; //拆箱

第二行,会在堆上实例化一个装箱的对象,并把a的值复制进去,b 引用的就是这个对象。第三行,会再次进行值复制,若 b 不再引用,则需等待垃圾回收。常见的事件管理器我们看一些常见的事件管理器使用代码:

[C#] 纯文本查看 复制代码

void Start()

{

    //注册事件

    EventManager.AddEventListener("Click", OnClick);

}

public void OnClick(object data)

{

    Debug.Log("clickBlock: " + data);

}

//派发事件

EventManager.dispatchEvent("Click", 123);

如上所述,若传递的是引用类型则不会有影响。但如果传递的是值类型,就会产生上述的性能消耗。泛型优化我们可以通过泛型去设置参数的类型,从而不需要通过 object 类型传递参数:

[C#] 纯文本查看 复制代码

public void Dispatch(string evt, T1 arg1, T2 arg2, T3 arg3, T4 arg4)

{

    Delegate[] methods = GetMethods(evt);

    if (methods != null)

    {

        foreach (Delegate m in methods)

        {

            try

            {

                ((Action)m)(arg1, arg2, arg3, arg4);

            }

            catch (Exception e) { LogError(e); }

        }

    }

}

将上面的代码,改为用泛型事件管理器:

[C#] 纯文本查看 复制代码

void Start()

{

    //注册事件

    EventDispatcher.global.AddListener("Click", OnClick);

}

public void OnClick(int data)

{

    Debug.Log("clickBlock: " + data);

}

//派发事件

EventDispatcher.global.Dispatch("Click", 123);

另:该事件管理器还支持【继承】与【实例化】,因此可以在非脚本对象和派生自MonoBehaviour的实例中使用。完整代码:

本帖隐藏的内容

[C#] 纯文本查看 复制代码

/*

* Author:  Rick

* Create:  2017/11/21 16:47:25

* Email:   rickjiangshu@gmail.com

* Follow:  https://github.com/RickJiangShu

*/

using System;

using System.Collections.Generic;

///

/// 事件派发器

/// 1. 优化装箱/拆箱

/// 2. 不使用闭包

///

public class EventDispatcher

{

    public static EventDispatcher global

    {

        get;

        private set;

    }

    static EventDispatcher()

    {

        global = new EventDispatcher();

    }

    private Dictionary _listeners = new Dictionary();

    public void AddListener(string evt, Action callback)

    {

        AddListener(evt, (Delegate)callback);

    }

    public void AddListener(string evt, Action callback)

    {

        AddListener(evt, (Delegate)callback);

    }

    public void AddListener(string evt, Action callback)

    {

        AddListener(evt, (Delegate)callback);

    }

    public void AddListener(string evt, Action callback)

    {

        AddListener(evt, (Delegate)callback);

    }

    public void AddListener(string evt, Action callback)

    {

        AddListener(evt, (Delegate)callback);

    }

    public void AddListener(string evt, Delegate callback)

    {

        Delegate listener;

        if (_listeners.TryGetValue(evt, out listener))

        {

            _listeners[evt] = Delegate.Combine(listener, callback);

        }

        else

        {

            _listeners[evt] = callback;

        }

    }

    public void RemoveListener(string evt, Action callback)

    {

        RemoveListener(evt, (Delegate)callback);

    }

    public void RemoveListener(string evt, Action callback)

    {

        RemoveListener(evt, (Delegate)callback);

    }

    public void RemoveListener(string evt, Action callback)

    {

        RemoveListener(evt, (Delegate)callback);

    }

    public void RemoveListener(string evt, Action callback)

    {

        RemoveListener(evt, (Delegate)callback);

    }

    public void RemoveListener(string evt, Action callback)

    {

        RemoveListener(evt, (Delegate)callback);

    }

    private void RemoveListener(string evt, Delegate callback)

    {

        Delegate listener;

        if (_listeners.TryGetValue(evt, out listener))

        {

            listener = Delegate.Remove(listener, callback);

            if (listener == null)

            {

                _listeners.Remove(evt);

            }

            else

            {

                _listeners[evt] = listener;

            }

        }

    }

    public void Dispatch(string evt, T1 arg1, T2 arg2, T3 arg3, T4 arg4)

    {

        Delegate[] methods = GetMethods(evt);

        if (methods != null)

        {

            foreach (Delegate m in methods)

            {

                try

                {

                    ((Action)m)(arg1, arg2, arg3, arg4);

                }

                catch (Exception e) { LogError(e); }

            }

        }

    }

    public void Dispatch(string evt, T1 arg1, T2 arg2, T3 arg3)

    {

        Delegate[] methods = GetMethods(evt);

        if (methods != null)

        {

            foreach (Delegate m in methods)

            {

                try

                {

                    ((Action)m)(arg1, arg2, arg3);

                }

                catch (Exception e) { LogError(e); }

            }

        }

    }

    public void Dispatch(string evt, T1 arg1, T2 arg2)

    {

        Delegate[] methods = GetMethods(evt);

        if (methods != null)

        {

            foreach (Delegate m in methods)

            {

                try

                {

                    ((Action)m)(arg1, arg2);

                }

                catch (Exception e) { LogError(e); }

            }

        }

    }

    public void Dispatch(string evt, T arg)

    {

        Delegate[] methods = GetMethods(evt);

        if (methods != null)

        {

            foreach (Delegate m in methods)

            {

                try

                {

                    ((Action)m)(arg);

                }

                catch (Exception e) { LogError(e); }

            }

        }

    }

    public void Dispatch(string evt)

    {

        Delegate[] methods = GetMethods(evt);

        if (methods != null)

        {

            foreach (Delegate m in methods)

            {

                try

                {

                    ((Action)m)();

                }

                catch (Exception e) { LogError(e); }

            }

        }

    }

    private Delegate[] GetMethods(string evt)

    {

        Delegate listener;

        if (_listeners.TryGetValue(evt, out listener))

        {

            return listener.GetInvocationList();

        }

        return null;

    }

    private static void LogError(Exception e)

    {

        UnityEngine.Debug.LogError(e);

    }

}

相关文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。