You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

315 lines
12 KiB

--===========================================================================--
-- --
-- System.Collections.Proxy --
-- --
--===========================================================================--
--===========================================================================--
-- Author : kurapica125@outlook.com --
-- URL : http://github.com/kurapica/PLoop --
-- Create Date : 2016/02/28 --
-- Update Date : 2018/05/12 --
-- Version : 1.1.0 --
--===========================================================================--
PLoop(function(_ENV)
import "System.Serialization"
--- The safe dictionary, it'll create the object as proxy to the real table
__Sealed__() __Serializable__() __Arguments__{ AnyType, AnyType }( Any, Any )
__NoNilValue__(false):AsInheritable() __NoRawSet__(false):AsInheritable()
class "System.Collections.Proxy" (function (_ENV, keytype, valtype)
extend "IDictionary" "ISerializable"
local RAW_HOLDER = {}
export {
ipairs = ipairs,
pairs = pairs,
GetErrorMessage = Struct.GetErrorMessage,
yield = coroutine.yield,
List[keytype], List[valtype]
}
if keytype ~= Any then
export { kvalid = getmetatable(keytype).ValidateValue, rawset = rawset }
end
if valtype ~= Any then
export { vvalid = getmetatable(valtype).ValidateValue, rawset = rawset }
end
-----------------------------------------------------------
-- serialization --
-----------------------------------------------------------
function Serialize(self, info)
local key = {}
local val = {}
local idx = 1
for k, v in self:GetIterator() do
key[idx]= k
val[idx]= v
idx = idx + 1
end
info:SetValue(1, List[keytype](key))
info:SetValue(2, List[valtype](val))
end
__Arguments__{ SerializationInfo }
function __new(_, info)
local key = info:GetValue(1, List[keytype])
local val = info:GetValue(2, List[valtype])
return this(_, key, val)
end
-----------------------------------------------------------
-- method --
-----------------------------------------------------------
function GetIterator(self)
return pairs(self[RAW_HOLDER])
end
--- Update the dictionary
if keytype == Any and valtype == Any then
__Arguments__{ RawTable }
function Update(self, dict)
for k, v in pairs(dict) do self[RAW_HOLDER][k] = v end
return self
end
__Arguments__{ IDictionary }
function Update(self, dict)
for k, v in dict:GetIterator() do self[RAW_HOLDER][k] = v end
return self
end
__Arguments__{ Callable, System.Any/nil, System.Any/nil }
function Update(self, iter, obj, idx)
for k, v in iter, obj, idx do self[RAW_HOLDER][k] = v end
return self
end
elseif keytype == Any and valtype ~= Any then
__Arguments__{ RawTable }
function Update(self, dict)
for k, v in pairs(dict) do
local ret, msg = vvalid(valtype, v, true)
if not msg then
self[RAW_HOLDER][k] = v
end
end
return self
end
__Arguments__{ IDictionary }
function Update(self, dict)
for k, v in dict:GetIterator() do
local ret, msg = vvalid(valtype, v, true)
if not msg then
self[RAW_HOLDER][k] = v
end
end
return self
end
__Arguments__{ Callable, System.Any/nil, System.Any/nil }
function Update(self, iter, obj, idx)
for k, v in iter, obj, idx do
local ret, msg = vvalid(valtype, v, true)
if not msg then
self[RAW_HOLDER][k] = v
end
end
return self
end
elseif keytype ~= Any and valtype == Any then
__Arguments__{ RawTable }
function Update(self, dict)
for k, v in pairs(dict) do
local ret, msg = kvalid(keytype, k, true)
if not msg then
self[RAW_HOLDER][k] = v
end
end
return self
end
__Arguments__{ IDictionary }
function Update(self, dict)
for k, v in dict:GetIterator() do
local ret, msg = kvalid(keytype, k, true)
if not msg then
self[RAW_HOLDER][k] = v
end
end
return self
end
__Arguments__{ Callable, System.Any/nil, System.Any/nil }
function Update(self, iter, obj, idx)
for k, v in iter, obj, idx do
local ret, msg = kvalid(keytype, k, true)
if not msg then
self[RAW_HOLDER][k] = v
end
end
return self
end
else
__Arguments__{ RawTable }
function Update(self, dict)
for k, v in pairs(dict) do
local ret, msg = kvalid(keytype, k, true)
if not msg then
ret, msg = vvalid(valtype, v, true)
if not msg then
self[RAW_HOLDER][k] = v
end
end
end
return self
end
__Arguments__{ IDictionary }
function Update(self, dict)
for k, v in dict:GetIterator() do
local ret, msg = kvalid(keytype, k, true)
if not msg then
ret, msg = vvalid(valtype, v, true)
if not msg then
self[RAW_HOLDER][k] = v
end
end
end
return self
end
__Arguments__{ Callable, System.Any/nil, System.Any/nil }
function Update(self, iter, obj, idx)
for k, v in iter, obj, idx do
local ret, msg = kvalid(keytype, k, true)
if not msg then
ret, msg = vvalid(valtype, v, true)
if not msg then
self[RAW_HOLDER][k] = v
end
end
end
return self
end
end
-----------------------------------------------------------
-- property --
-----------------------------------------------------------
--- Gets or sets the value associated with the specified key
__Indexer__(keytype ~= Any and keytype or nil)
property "Item" {
get = function(self, key)
return self[RAW_HOLDER][key]
end,
set = function(self, key, value)
self[RAW_HOLDER][key] = value
end,
type = valtype ~= Any and valtype or nil,
}
-----------------------------------------------------------
-- constructor --
-----------------------------------------------------------
__Arguments__{ }
function __new() return { [RAW_HOLDER] = {} } end
__Arguments__{ RawTable }
function __new(_, dict) return { [RAW_HOLDER] = dict }, true end
__Arguments__{ RawTable + IList, RawTable + IList }
function __new(_, lstKey, lstValue)
local dict = {}
local iter, o, idx, value = (lstValue.GetIterator or ipairs)(lstValue)
for _, key in (lstValue.GetIterator or ipairs)(lstKey) do
idx, value = iter(o, idx)
if idx then
dict[key] = value
else
break
end
end
return { [RAW_HOLDER] = dict }, true
end
__Arguments__{ RawTable + IList, Any }
function __new(_, lstKey, value)
local dict = {}
for _, key in (lstKey.GetIterator or ipairs)(lstKey) do
dict[key] = value
end
return { [RAW_HOLDER] = dict }, true
end
__Arguments__{ IDictionary }
function __new(_, dict)
local dict = {}
for key, value in dict:GetIterator() do
dict[key] = value
end
return { [RAW_HOLDER] = dict }, true
end
__Arguments__{ Callable, Any/nil, Any/nil }
function __new(_, iter, obj, idx)
local dict = {}
for key, value in iter, obj, idx do
dict[key] = value
end
return { [RAW_HOLDER] = dict }, true
end
if keytype ~= Any and valtype ~= Any then
function __ctor(self)
local msg
for k, v in self:GetIterator() do
k, msg = kvalid(keytype, k)
if msg then throw(GetErrorMessage(msg, "field")) end
v, msg = vvalid(valtype, v)
if msg then throw(GetErrorMessage(msg, "value")) end
self[k]= v
end
end
elseif keytype ~= Any then
function __ctor(self)
local msg
for k, v in self:GetIterator() do
k, msg = kvalid(keytype, k)
if msg then throw(GetErrorMessage(msg, "field")) end
end
end
elseif valtype ~= Any then
function __ctor(self)
local msg
for k, v in self:GetIterator() do
v, msg = vvalid(valtype, v)
if msg then throw(GetErrorMessage(msg, "value")) end
self[k]= v
end
end
end
-----------------------------------------------------------
-- meta-method --
-----------------------------------------------------------
if keytype ~= Any or valtype ~= Any then
__Arguments__{ keytype, valtype }
end
function __newindex(self, key, val)
self[RAW_HOLDER][key]= val
end
function __index(self, key)
return self[RAW_HOLDER][key]
end
end)
end)