mercredi 2 octobre 2019

C# Expression Specified cast is not valid

How to pass parameters using Expression.Invoke()?

If I use EventName = "ParameterlessAction" (trying to subscribe on parameterless Action)

-> everything works: created delegate can be subscribed on parameterless Action,

but if I try to use EventName = "BoolAction" (trying to subscribe on Action<bool>)

-> InvalidOperationException: Incorrect number of arguments cause I don't handle any parameters.

public class DelegateTest
    {
        public event Action ParameterlessAction;
        public event Action<bool> BoolAction;
        public DelegateTest()
        {
            string EventName = "ParameterlessAction";
            EventInfo eventInfo = typeof(DelegateTest).GetEvent(EventName);
            MethodInfo methodInfo = eventInfo.EventHandlerType.GetMethod("Invoke");
            var parameters = methodInfo.GetParameters();
            Type[] types = new Type[parameters.Length];
            for (int i = 0; i < types.Length; i++)
            {
                types[i] = parameters[i].ParameterType;
            }
            Delegate del = CreateDelegate(types, typeof(void));
            eventInfo.AddEventHandler(this, del);
            ParameterlessAction?.Invoke();
            BoolAction?.Invoke(false);
            BoolAction?.Invoke(true);
        }
        public void PrintMessage(string msg)
        {
            Console.WriteLine(msg);
        }
        public Delegate CreateDelegate(Type[] parameterTypes, Type returnType)
        {
            PrintMessage("Total params: " + parameterTypes.Length);
            var parameters = parameterTypes.Select(Expression.Parameter).ToArray();
            Expression body;
            if (parameters.Length == 0)
            {
                PrintMessage("Creating parameterless lambda...");
                Expression<Action> parameterlessDel = () => PrintMessage("Parameterless");
                InvocationExpression invocator = Expression.Invoke(parameterlessDel);
                body = invocator;
            }
            else if (parameters.Length == 1)
            {
                Type type = parameters[0].Type;
                if (type == typeof(bool))
                {
                    PrintMessage("Creating <bool> lambda...");
                    Expression<Action<bool>> boolDel = (b) => PrintMessage("Bool[" + b.ToString() + "]");


                    //How to pass parameter here?


                    InvocationExpression invocator = Expression.Invoke(boolDel);
                    body = invocator;
                }
                else
                {
                    throw new Exception();
                }
            }
            else
            {
                throw new Exception();
            }
            var lambda = Expression.Lambda(body, false, parameters);
            return lambda.Compile();
        }
    }




Aucun commentaire:

Enregistrer un commentaire