public TRes SendMessage <TReq, TRes>(EntityIdentifier entityId, TReq message) where TReq : RequestMessage <TRes> where TRes : ResponseMessage { if (!_messageHandlers.TryGetValue(message.GetType(), out var handlerSubs)) { return(null); } var allComponents = GetAllComponents(entityId); var allComponentTypes = new HashSet <Type>(allComponents.Select(c => c.GetType())); var entityAssemblage = new Assemblage(allComponentTypes); if (!_handlerChainExecutorCache.TryGetValue(message.GetType(), out var executor)) { var method = typeof(Engine).GetMethod("ExecuteHandlerChain", BindingFlags.NonPublic | BindingFlags.Static); executor = (Func <List <Tuple <AssemblageFilter, Delegate> >, int, object, EntityIdentifier, Assemblage, object>)method.MakeGenericMethod(typeof(TReq), typeof(TRes)).CreateDelegate(typeof(Func <List <Tuple <AssemblageFilter, Delegate> >, int, object, EntityIdentifier, Assemblage, object>)); _handlerChainExecutorCache.Add(message.GetType(), executor); } return((TRes)executor(handlerSubs, 0, message, entityId, entityAssemblage)); }
public AssemblageFilter(IEnumerable <Type> componentTypes) { _filter = new Assemblage(componentTypes); }
public bool IsMatch(Assemblage assemblage) { return(_filter.IsSubsetOf(assemblage)); }
public bool IsSubsetOf(Assemblage assemblage) { return(_types.IsSubsetOf(assemblage._types)); }
private static TRes ExecuteHandlerChain <TReq, TRes>(List <Tuple <AssemblageFilter, Delegate> > handlers, int index, object message, EntityIdentifier entityId, Assemblage entityAssemblage) where TReq : RequestMessage <TRes> where TRes : ResponseMessage { for (; index < handlers.Count; index++) { if (handlers[index].Item1.IsMatch(entityAssemblage)) { return(((Func <TReq, EntityIdentifier, Func <TReq, EntityIdentifier, TRes>, TRes>)handlers[index].Item2)((TReq)message, entityId, (m, e) => ExecuteHandlerChain <TReq, TRes>(handlers, index + 1, (TReq)message, entityId, entityAssemblage))); } } return(null); }