Пример #1
0
        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);
        }
Пример #2
0
 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;
 }
Пример #3
0
 /// <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()));
 }
Пример #4
0
 public Bus(ActorId owner, ActorRegistry registry, int throwAfterNTrials, IMessageWriter writer)
 {
     Init(owner, registry, throwAfterNTrials, writer);
 }