private Func <object, JsValue[], object> CreateInvoker(MethodInfo method) { var methodParameters = method.GetParameters(); var expressionParamThis = Expression.Parameter(typeof(object), "clrThis"); var expressionParamArgs = Expression.Parameter(typeof(JsValue[]), "jsArgs"); var arguments = methodParameters.Select((x, idx) => { if (x.GetCustomAttribute <ParamArrayAttribute>() != null) { var getItemExpression = Expression.Call(GetType(), nameof(Slice), new Type[0], expressionParamArgs, Expression.Constant(idx)); return(_converter.CreateConverterExpr(x.ParameterType, getItemExpression, expressionParamThis, false)); } else { var getItemExpression = (Expression)Expression.ArrayAccess(expressionParamArgs, Expression.Constant(idx)); return (Expression.Condition( Expression.LessThan(Expression.Constant(idx), Expression.ArrayLength(expressionParamArgs)), _converter.CreateConverterExpr(x.ParameterType, getItemExpression, expressionParamThis, method.GetInterfaceDeclarationsForMethod().Any(p => p.GetParameters()[idx].GetCustomAttribute <JsExpandArrayAttribute>() != null)), Expression.Convert( x.HasDefaultValue ? Expression.Constant(x.DefaultValue) : Expression.Constant(GetDefault(x.ParameterType)), x.ParameterType) )); } }).ToArray(); var expressionCall = Expression.Call( Expression.Convert(expressionParamThis, method.DeclaringType), method, arguments); if (method.ReturnParameter.ParameterType == typeof(void)) { var act = Expression.Lambda <Action <object, JsValue[]> >( expressionCall, expressionParamThis, expressionParamArgs).Compile(); return((clrThis, jsArgs) => { act(clrThis, jsArgs); return null; }); } var invoker = Expression.Lambda <Func <object, JsValue[], object> >( Expression.Convert(expressionCall, typeof(object)), expressionParamThis, expressionParamArgs).Compile(); return(invoker); }
private static Action <object, JsValue> CreateSetter(DomConverter converter, PropertyInfo property) { var expThisArg = Expression.Parameter(typeof(object), "clrThis"); var expValueArg = Expression.Parameter(typeof(JsValue), "jsValue"); var setterExpression = Expression.Assign( Expression.Property(Expression.Convert(expThisArg, property.DeclaringType), property), converter.CreateConverterExpr(property.PropertyType, expValueArg, expThisArg)); var setterLambda = Expression.Lambda <Action <object, JsValue> >(setterExpression, expThisArg, expValueArg) .Compile(); return(setterLambda); }