public static void RegistorEventEntry()
    {
        // do nothing if already registered
        if (eventTable.Count > 0)
        {
            return;
        }

        FieldInfo[] fileds = typeof(ViveShare_Event).GetFields();

        foreach (FieldInfo fieldInfo in fileds)
        {
            object        obj       = fieldInfo.GetValue(null);
            Type          objType   = obj.GetType();
            ViveEventBase eventBase = (ViveEventBase)obj;

            MethodInfo[] methods = objType.GetMethods();
            foreach (MethodInfo method in methods)
            {
                if (method.Name == "Invoke")
                {
                    EventTableEntry tableEntry = new EventTableEntry();
                    tableEntry.eventObj = obj;
                    tableEntry.method   = method;

                    eventTable.Add(eventBase.eventID, tableEntry);

                    break;
                }
            }
        }
    }
    // event invoke by event id
    public static void InvokeEventByID(string eventID, params object[] args)
    {
        EventTableEntry evnt = eventTable[eventID];

        if (evnt != null)
        {
            evnt.method.Invoke(evnt.eventObj, args);
        }
    }