Example #1
0
        public ObserverGrain()
        {
            GrainType = GetType();
            var handlerAttributes = GrainType.GetCustomAttributes(typeof(IgnoreEventsAttribute), false);

            if (handlerAttributes.Length > 0)
            {
                handlerAttribute = (IgnoreEventsAttribute)handlerAttributes[0];
            }
            else
            {
                handlerAttribute = default;
            }
            var methods = GetType().GetMethods().Where(m =>
            {
                var parameters = m.GetParameters();
                return(parameters.Length >= 1 && parameters.Any(p => typeof(IEvent).IsAssignableFrom(p.ParameterType) && !p.ParameterType.IsInterface));
            }).ToList();
            var dynamicMethod = new DynamicMethod($"Handler_Invoke", typeof(Task), new Type[] { typeof(object), typeof(IEvent), typeof(EventBase) }, GrainType, true);
            var ilGen         = dynamicMethod.GetILGenerator();
            var switchMethods = new List <SwitchMethodEmit>();

            for (int i = 0; i < methods.Count; i++)
            {
                var method       = methods[i];
                var methodParams = method.GetParameters();
                var caseType     = methodParams.Single(p => typeof(IEvent).IsAssignableFrom(p.ParameterType)).ParameterType;
                switchMethods.Add(new SwitchMethodEmit
                {
                    Mehod        = method,
                    CaseType     = caseType,
                    DeclareLocal = ilGen.DeclareLocal(caseType),
                    Lable        = ilGen.DefineLabel(),
                    Parameters   = methodParams,
                    Index        = i
                });
            }
            var sortList = new List <SwitchMethodEmit>();

            foreach (var item in switchMethods.Where(m => !typeof(IEvent).IsAssignableFrom(m.CaseType.BaseType)))
            {
                sortList.Add(item);
                GetInheritor(item, switchMethods, sortList);
            }
            sortList.Reverse();
            foreach (var item in switchMethods)
            {
                if (!sortList.Contains(item))
                {
                    sortList.Add(item);
                }
            }
            var defaultLabel = ilGen.DefineLabel();
            var lastLable    = ilGen.DefineLabel();
            var declare_1    = ilGen.DeclareLocal(typeof(Task));

            foreach (var item in sortList)
            {
                ilGen.Emit(OpCodes.Ldarg_1);
                ilGen.Emit(OpCodes.Isinst, item.CaseType);
                if (item.Index > 3)
                {
                    if (item.DeclareLocal.LocalIndex > 0 && item.DeclareLocal.LocalIndex <= 255)
                    {
                        ilGen.Emit(OpCodes.Stloc_S, item.DeclareLocal);
                        ilGen.Emit(OpCodes.Ldloc_S, item.DeclareLocal);
                    }
                    else
                    {
                        ilGen.Emit(OpCodes.Stloc, item.DeclareLocal);
                        ilGen.Emit(OpCodes.Ldloc, item.DeclareLocal);
                    }
                }
                else
                {
                    if (item.Index == 0)
                    {
                        ilGen.Emit(OpCodes.Stloc_0);
                        ilGen.Emit(OpCodes.Ldloc_0);
                    }
                    else if (item.Index == 1)
                    {
                        ilGen.Emit(OpCodes.Stloc_1);
                        ilGen.Emit(OpCodes.Ldloc_1);
                    }
                    else if (item.Index == 2)
                    {
                        ilGen.Emit(OpCodes.Stloc_2);
                        ilGen.Emit(OpCodes.Ldloc_2);
                    }
                    else
                    {
                        ilGen.Emit(OpCodes.Stloc_3);
                        ilGen.Emit(OpCodes.Ldloc_3);
                    }
                }
                ilGen.Emit(OpCodes.Brtrue, item.Lable);
            }
            ilGen.Emit(OpCodes.Br, defaultLabel);
            foreach (var item in sortList)
            {
                ilGen.MarkLabel(item.Lable);
                ilGen.Emit(OpCodes.Ldarg_0);
                //加载第一个参数
                if (item.Parameters[0].ParameterType == item.CaseType)
                {
                    LdEventArgs(item, ilGen);
                }
                else if (item.Parameters[0].ParameterType == typeof(EventBase))
                {
                    ilGen.Emit(OpCodes.Ldarg_2);
                }
                //加载第二个参数
                if (item.Parameters.Length == 2)
                {
                    if (item.Parameters[1].ParameterType == item.CaseType)
                    {
                        LdEventArgs(item, ilGen);
                    }
                    else if (item.Parameters[1].ParameterType == typeof(EventBase))
                    {
                        ilGen.Emit(OpCodes.Ldarg_2);
                    }
                }
                ilGen.Emit(OpCodes.Call, item.Mehod);
                if (item.DeclareLocal.LocalIndex > 0 && item.DeclareLocal.LocalIndex <= 255)
                {
                    ilGen.Emit(OpCodes.Stloc_S, declare_1);
                }
                else
                {
                    ilGen.Emit(OpCodes.Stloc, declare_1);
                }
                ilGen.Emit(OpCodes.Br, lastLable);
            }
            ilGen.MarkLabel(defaultLabel);
            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldarg_1);
            ilGen.Emit(OpCodes.Call, GrainType.GetMethod(nameof(DefaultHandler)));
            if (declare_1.LocalIndex > 0 && declare_1.LocalIndex <= 255)
            {
                ilGen.Emit(OpCodes.Stloc_S, declare_1);
            }
            else
            {
                ilGen.Emit(OpCodes.Stloc, declare_1);
            }
            ilGen.Emit(OpCodes.Br, lastLable);
            //last
            ilGen.MarkLabel(lastLable);
            if (declare_1.LocalIndex > 0 && declare_1.LocalIndex <= 255)
            {
                ilGen.Emit(OpCodes.Ldloc_S, declare_1);
            }
            else
            {
                ilGen.Emit(OpCodes.Ldloc, declare_1);
            }
            ilGen.Emit(OpCodes.Ret);
            handlerInvokeFunc = (Func <object, IEvent, EventBase, Task>)dynamicMethod.CreateDelegate(typeof(Func <object, IEvent, EventBase, Task>));