local BaseData = class("BaseData") function BaseData:ctor(...) self.data = {} self.data.__parent = self local innerData = nil innerData = { __index = function (t, key) return innerData[key] end, __newindex = function (t, key, value) local preValue = innerData[key] innerData[key] = value t.__parent:invoke(key, preValue, value) end } setmetatable(self.data, innerData) self.bindList = {} self.forceList = {} self._baseInvokeCount = 0 end function BaseData:invoke(name, preValue, value) self._baseInvokeCount = self._baseInvokeCount + 1 if (self.forceList[name] or preValue ~= value) or type(preValue) == "table" then self.forceList[name] = nil if self.bindList[name] then for _, info in ipairs(self.bindList[name]) do info.bindFunc(info.binder, value) end end end self._baseInvokeCount = self._baseInvokeCount - 1 if self._baseInvokeCount > 0 then -- 说明还在递归中 return end if self._baseRemoveFlag then self._baseRemoveFlag = false if self._waitRemoveMap then for key, v in pairs(self._waitRemoveMap) do local list = self.bindList[key] if list then for i = #list, 1, -1 do if list[i] and list[i].waitRemove then table.remove(list, i) end end end self._waitRemoveMap[key] = nil end end end end function BaseData:bind(name, binder, bindFunc, immediately) if not self.bindList[name] then self.bindList[name] = {} end local unique = true for i, info in ipairs(self.bindList[name]) do if info and binder and info.binder == binder then self.bindList[name][i].bindFunc = bindFunc unique = false break end end if unique then table.insert(self.bindList[name], {binder = binder, bindFunc = bindFunc}) end if immediately then self:invoke(name, nil, self.data[name]) end end function BaseData:unBind(name, binder) if self.bindList[name] then for i, info in ipairs(self.bindList[name]) do if info.binder == binder then if self._baseInvokeCount > 0 then -- 正在invoke过程中 info.waitRemove = true self._baseRemoveFlag = true if self._waitRemoveMap == nil then self._waitRemoveMap = {} end self._waitRemoveMap[name] = true else table.remove(self.bindList[name], i) end break end end end end function BaseData:setForceInvoke(name, value) self.forceList[name] = true self.data[name] = value end function BaseData:clearBind(name) if self.bindList[name] then self.bindList[name] = nil end end function BaseData:clearBindAll() self.bindList = {} end function BaseData:clear() end if NOT_PUBLISH then function BaseData:_typeValid(name) local value = self.data[name] local vt = type(value) if vt == "string" or vt == "number" or vt == "nil" or vt == "boolean" or vt == "table" then return true end return false end BaseData._releaseBind = BaseData.bind function BaseData:bind(name, ...) if not self:_typeValid(name) then Logger.logFatal("%s:%s type is valid", self.__cname, name) end self:_releaseBind(name, ...) end end return BaseData