public void Add(Delegate handler, RegisterEventHandler eventInfo)
 {
     dict.Add(handler, eventInfo);
 }
 public void Add(Delegate handler, RegisterEventHandler eventInfo)
 {
     dict.Add(handler, eventInfo);
 }
        /// <summary>[-0, +2, e]
        /// Returns to Lua the value of a member or a delegate to call it, depending on the type of the member.
        /// Works with static or instance members. Uses reflection to find members,
        /// and stores the reflected MemberInfo object in a cache (indexed by <paramref name="objType"/> and <paramref name="methodName"/>).
        /// </summary>
        /// <exception cref="ArgumentNullException"><paramref name="objType"/> and <paramref name="methodName"/> are required</exception>
        int getMember(lua.State L, IReflect objType, object obj, string methodName, BindingFlags bindingType)
        {
            Debug.Assert(interpreter.IsSameLua(L));
            Debug.Assert(objType != null && methodName != null);

            Debug.Assert((obj == null) == (objType is ProxyType));
            Debug.Assert((obj == null) != (objType is Type));
            Debug.Assert((obj == null) == ((bindingType & BindingFlags.Static) == BindingFlags.Static));
            Debug.Assert((obj == null) != ((bindingType & BindingFlags.Instance) == BindingFlags.Instance));

            MemberInfo member       = null;
            object     cachedMember = checkMemberCache(objType, methodName);

            if (cachedMember != null)
            {
                var cachedMethod = cachedMember as lua.CFunction;
                if (cachedMethod != null)
                {
                    luaclr.pushcfunction(L, cachedMethod);
                    lua.pushboolean(L, true);
                    return(2);
                }
                Debug.Assert(cachedMember is MemberInfo);
                member = (MemberInfo)cachedMember;
            }
            else
            {
                MemberInfo[] members = objType.GetMember(methodName, bindingType | luanet.LuaBindingFlags);
                if (members.Length != 0)
                {
                    member = members[0];
                                        #if DEBUG
                    if (!(members.Length == 1 || member is MethodBase))                     // todo
                    {
                        return(luaL.error(L, "Overloads for members other than methods are not implemented."));
                    }
                                        #endif
                }
            }

            object value = null;

            switch (member == null ? MemberTypes.All : member.MemberType)
            {
            default:             // not found or found a constructor
                // kevinh - we want to throw an error because merely returning 'nil' in this case
                // is not sufficient.  valid data members may return nil and therefore there must be some
                // way to know the member just doesn't exist.
                return(luaL.error(L, string.Format("'{0}' does not contain a definition for '{1}'", objType.UnderlyingSystemType.FullName, methodName)));

            case MemberTypes.Method:
                var wrapper = new lua.CFunction((new LuaMethodWrapper(translator, objType, methodName, bindingType)).call);

                if (cachedMember == null)
                {
                    setMemberCache(objType, methodName, wrapper);
                }
                luaclr.pushcfunction(L, wrapper);
                lua.pushboolean(L, true);
                return(2);

            case MemberTypes.Field:
                if (!translator.memberIsAllowed(member))
                {
                    return(luaL.error(L, "field read failed (access denied)"));
                }
                try { value = ((FieldInfo)member).GetValue(obj); }
                catch { goto default; }
                translator.push(L, value);
                break;

            case MemberTypes.Property:
                // todo: support indexed properties
                if (!translator.memberIsAllowed(member))
                {
                    return(luaL.error(L, "property call failed (access denied)"));
                }
                try { value = ((PropertyInfo)member).GetValue(obj, null); }
                catch (TargetInvocationException ex) { return(translator.throwError(L, luaclr.verifyex(ex.InnerException))); }
                catch { goto default; }
                translator.push(L, value);
                break;

            case MemberTypes.Event:
                if (!translator.memberIsAllowed(member))
                {
                    return(luaL.error(L, "event read failed (access denied)"));
                }
                value = new RegisterEventHandler(translator.pendingEvents, obj, (EventInfo)member);
                translator.push(L, value);
                break;

            case MemberTypes.NestedType:
                var nestedType = (Type)member;
                if (translator.FindType(nestedType))                 // don't hand out class references unless loaded/whitelisted
                {
                    ObjectTranslator.pushType(L, nestedType);
                }
                else
                {
                    lua.pushnil(L);
                }
                break;
            }

            if (cachedMember == null)
            {
                setMemberCache(objType, methodName, member);
            }
            // push false because we are NOT returning a function (see luaIndexFunction)
            lua.pushboolean(L, false);
            return(2);
        }