private static DynamicMethod BuildDispatchingMethod(IActor handler, IStructSizeCounter counter, Func <Type, int> messageIdGetter) { var handlerType = handler.GetType(); var handleMethods = ActorRegistry.GetHandleMethods(handlerType) .ToDictionary(m => messageIdGetter(m.GetParameters()[1].ParameterType.GetElementType()), m => m) .OrderBy(kvp => kvp.Key) .ToArray(); var dm = new DynamicMethod("ReadMessagesFor_" + handlerType.Namespace.Replace(".", "_") + handlerType.Name, typeof(void), new[] { typeof(MessageReader), typeof(int), typeof(ByteChunk) }, handlerType.Assembly.Modules.First(), true); var actorField = typeof(MessageReader).GetFields(BindingFlags.NonPublic | BindingFlags.Instance) .Single(fi => fi.FieldType == typeof(IActor)); var il = dm.GetILGenerator(); // push handler il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, actorField); il.Emit(OpCodes.Castclass, handlerType); var endLbl = il.DefineLabel(); // dispatch foreach (var method in handleMethods) { var lbl = il.DefineLabel(); il.Emit(OpCodes.Ldarg_1); // messageTypeId il.Emit(OpCodes.Ldc_I4, method.Key); il.Emit(OpCodes.Ceq); il.Emit(OpCodes.Brfalse_S, lbl); // push envelope il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldfld, typeof(ByteChunk).GetField("Pointer")); //var messageType = method.Value.GetParameters()[1].ParameterType.GetElementType(); //il.Emit(OpCodes.Ldc_I4, (int)Marshal.OffsetOf(messageType, Envelope.FieldName)); //il.Emit(OpCodes.Add); // push message il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldfld, typeof(ByteChunk).GetField("Pointer")); il.EmitCall(OpCodes.Callvirt, method.Value, null); il.Emit(OpCodes.Br_S, endLbl); il.MarkLabel(lbl); } // nothing was called, pop il.Emit(OpCodes.Pop); // end label il.MarkLabel(endLbl); il.Emit(OpCodes.Ret); return(dm); }
internal void Init(ActorId owner, ActorRegistry registry, int throwAfterNTrials, IMessageWriter writer) { if (_sealed) { throw new InvalidOperationException("The bus has been already initialized"); } _owner = owner; _registry = registry; _throwAfterNTrials = throwAfterNTrials; _writer = writer; _sealed = true; }
/// <summary> /// Gets all the message types handled by the given <paramref name="handlerType"/> /// </summary> private static IEnumerable <Type> GetHandledMessageTypes(Type handlerType) { return (ActorRegistry.GetHandleMethods(handlerType) .Select(m => m.GetParameters()[1].ParameterType.GetElementType())); }
public Bus(ActorId owner, ActorRegistry registry, int throwAfterNTrials, IMessageWriter writer) { Init(owner, registry, throwAfterNTrials, writer); }