Esempio n. 1
0
        private void GenerateDebouncedHandler(ResolvedArguments resolvedArguments, MethodInfo innerMethod, ILGenerator body)
        {
            var argTypes = new Type[resolvedArguments.Types.Length + 1];

            Array.Copy(resolvedArguments.Types, 0, argTypes, 1, resolvedArguments.Types.Length);
            argTypes[0] = _source.DataContext.GetType();
            var debouncerModel = GenerateDebouncer(argTypes, innerMethod);

            body.Emit(OpCodes.Newobj, debouncerModel.Constructor);

            body.Emit(OpCodes.Ldarg_0);
            body.Emit(OpCodes.Ldfld, _timerField);
            var continuation = body.DefineLabel();

            body.Emit(OpCodes.Brfalse_S, continuation);
            body.Emit(OpCodes.Ldarg_0);
            body.Emit(OpCodes.Ldfld, _timerField);
            body.Emit(OpCodes.Call, typeof(Timer).GetMethod(nameof(Timer.Dispose),
                                                            BindingFlags.Instance | BindingFlags.Public, null, new Type[0], null));
            body.MarkLabel(continuation);

            body.Emit(OpCodes.Ldftn, debouncerModel.Method);
            body.Emit(OpCodes.Newobj, typeof(TimerCallback).GetConstructors()[0]);
            body.Emit(OpCodes.Call, typeof(SynchronizationContext).GetProperty(nameof(SynchronizationContext.Current)).GetGetMethod());
            body.Emit(OpCodes.Ldc_I4, _eventBinding.Debounce.Value);
            body.Emit(OpCodes.Ldc_I4_M1);
            body.Emit(OpCodes.Newobj, typeof(Timer).GetConstructor(
                          BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance,
                          null, new[] { typeof(TimerCallback), typeof(object), typeof(int), typeof(int) }, null));

            var variable = body.DeclareLocal(typeof(Timer));

            body.Emit(OpCodes.Stloc, variable);
            body.Emit(OpCodes.Ldarg_0);
            body.Emit(OpCodes.Ldloc, variable);
            body.Emit(OpCodes.Stfld, _timerField);
        }
        public Value Execute(ValueContainer scopes, object obj)
        {
            Value[] arguments;

            if (ResolvedArguments != null)
            {
                arguments = ResolvedArguments.ToArray();
            }
            else
            {
                arguments = Arguments?.Select(x => x?.Process(scopes)).Where(x => x != null).ToArray();
            }

            if (obj.GetType() == typeof(Value))
            {
                var valueObj = (Value)obj;

                var constructors = valueObj.ContainsWithTreeScan("constructor");

                var possibleConstructor =
                    constructors?.FirstOrDefault(x =>
                {
                    if (x.RawValue is FunctionAbstract)
                    {
                        return((x.RawValue as FunctionAbstract).Arguments.Count == arguments.Length);
                    }

                    if (x.RawValue is Delegate)
                    {
                        return(new FunctionAbstract(x.RawValue).Arguments.Count == arguments.Length);
                    }

                    if (!(x.RawValue is LambdaExpression))
                    {
                        throw new NotSupportedException("Why is a constructor a value!");
                    }

                    return(((LambdaExpression)x.RawValue).Arguments.Count == arguments.Length);
                });

                var functions = valueObj.Values.Where(x => x.Key.Trim() == TrimmedFunction && x.Value.IsFunction).Select(x => x.Value).ToList();

                if (valueObj.IsNull && functions.Any())
                {
                    var possibleMethod =
                        functions.FirstOrDefault(x =>
                    {
                        if (x.RawValue is FunctionAbstract)
                        {
                            return((x.RawValue as FunctionAbstract).Arguments.Count == arguments.Length);
                        }

                        if (!(x.RawValue is LambdaExpression))
                        {
                            throw new NotSupportedException("Why is a constructor a value!");
                        }

                        return(((LambdaExpression)x.RawValue).Arguments.Count == arguments.Length);
                    });

                    if (possibleMethod != null)
                    {
                        return(InvokeSomething(scopes, arguments, possibleMethod.RawValue));
                    }
                    else
                    {
                        throw new NotSupportedException($"The method \"{TrimmedFunction}\" cannot be not found within scope!");
                    }
                }
                else if (valueObj.IsFunction)
                {
                    var func = valueObj.RawValue;

                    if (func is Delegate)
                    {
                        return(RetypeValue(InvokeMethod((Delegate)func, arguments), scopes));
                    }
                    if (func is Expression)
                    {
                        return(InvokeLambda(scopes, arguments, (LambdaExpression)func));
                    }
                    if (func is FunctionAbstract)
                    {
                        return(InvokeSomething(scopes, arguments, func));
                    }
                    throw new NotSupportedException();
                }
                else if (possibleConstructor != null)
                {
                    //We should create a new context for the object

                    var contextWithNewObject = scopes.Copy();

                    var vel = scopes.Engine.NewValue(null, valueObj);
                    contextWithNewObject.Push(vel);
                    vel.ConstructorClass = valueObj;
                    var constructorReturn = InvokeSomething(contextWithNewObject, arguments, possibleConstructor.RawValue);
                    return(vel);
                }
                else
                {
                    throw new NotSupportedException($"Object {obj} is not executable!");
                }
            }

            throw new NotSupportedException();
        }