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(); }