public static Task <TRes> Transform <TArg, TRes>(this Task <TArg> task, Func <TArg, TRes> transformer) { if (transformer == null) { ExThrowers.ThrowArgNull(nameof(transformer)); } var tcs = new TaskCompletionSource <TRes>(); task.ContinueWith(t => { if (t.IsFaulted) { tcs.SetException(t.Exception); } else if (t.IsCanceled) { tcs.SetCanceled(); } else { try { tcs.SetResult(transformer(t.Result)); } catch (Exception ex) { tcs.SetException(ex); } } }, TaskContinuationOptions.ExecuteSynchronously); return(tcs.Task); }
public static T CreateCustomDelegate <T>(this MethodInfo m, params Type[] genericArgs) where T : class { var delType = typeof(T); if (!typeof(Delegate).IsAssignableFrom(delType)) { ExThrowers.ThrowArgEx("T is not Delegate type"); } if (genericArgs == null) { ExThrowers.ThrowArgNull(nameof(genericArgs)); } var delInvokeM = delType.GetMethod("Invoke"); var delParams = delInvokeM.GetParameters(); var parentType = m.DeclaringType; var retType = m.ReturnType; var args = m.GetParameters().Select(p => p.ParameterType).ToArray(); if (delParams.Length != (args.Length + (m.IsStatic ? 0 : 1))) { ExThrowers.ThrowArgEx("Number of Delegate arguments does not match method"); } var argsParams = delParams.Select(p => Expression.Parameter(p.ParameterType, p.Name)).ToArray(); var callParams = m.IsStatic ? argsParams : argsParams.Skip(1); var callArgs = callParams.Select((arg, i) => { if (arg.Type == args[i]) { return((Expression)arg); } return(Expression.Convert(arg, args[i])); }); var callInstParam = m.IsStatic ? null : ((parentType == typeof(object)) ? (Expression)argsParams[0] : Expression.Convert(argsParams[0], parentType)); Expression call = m.IsStatic ? Expression.Call(m.DeclaringType, m.Name, genericArgs, callArgs.ToArray()) : Expression.Call(callInstParam, m.Name, genericArgs, callArgs.ToArray()); if (retType == typeof(void)) { if (delInvokeM.ReturnType != typeof(void)) { call = Expression.Block(call, Expression.Default(delInvokeM.ReturnType)); // Return default(ReturnType) } } else if (retType != delInvokeM.ReturnType) { if (delInvokeM.ReturnType != typeof(void) && (retType.IsValueType || delInvokeM.ReturnType.IsValueType)) { call = Expression.Convert(call, delInvokeM.ReturnType); } } var expr = Expression.Lambda(delType, call, argsParams); return(expr.Compile() as T); }
public static bool TryGetValueTupleTypes(this Type type, out Type[] types) { if (type == null) { ExThrowers.ThrowArgNull(nameof(type)); } types = null; if (!type.FullName.StartsWith("System.ValueTuple`", StringComparison.Ordinal)) { return(false); } types = type.GetGenericArguments(); return(true); }
public static MethodInvoker DelegateForMethod(this MethodInfo m, params Type[] genericArgs) { if (genericArgs == null) { ExThrowers.ThrowArgNull(nameof(genericArgs)); } var parentType = m.DeclaringType; var retType = m.ReturnType; var args = m.GetParameters().Select(p => p.ParameterType).ToArray(); var instParam = Expression.Parameter(typeof(object), "instance"); var argsParam = Expression.Parameter(typeof(object[]), "args"); var indexedParams = args.Select((arg, i) => { Expression argExpr = Expression.ArrayAccess(argsParam, Expression.Constant(i)); if (arg == typeof(object)) { return(argExpr); } return(Expression.Convert(argExpr, arg)); }).ToArray(); Expression call = m.IsStatic ? Expression.Call(m.DeclaringType, m.Name, genericArgs, indexedParams) : Expression.Call((parentType == typeof(object)) ? (Expression)instParam : Expression.Convert(instParam, parentType), m.Name, genericArgs, indexedParams); Expression <Action <object[]> > callArgEx = a => ExThrowers.ThrowArgEx($"Number of supplied arguments ({a.Length}) does not match number of method arguments ({args.Length})"); var checkerExpr = Expression.IfThen(Expression.NotEqual(Expression.ArrayLength(argsParam), Expression.Constant(args.Length)), Expression.Invoke(callArgEx, argsParam)); var checkedCall = Expression.Block(checkerExpr, call); if (retType == typeof(void)) { call = Expression.Block(checkedCall, Expression.Constant(null, typeof(object))); // Return null } else if (retType.IsValueType) { call = Expression.Convert(checkedCall, typeof(object)); // Box } else { call = checkedCall; } var expr = Expression.Lambda(typeof(MethodInvoker), call, instParam, argsParam); return((MethodInvoker)expr.Compile()); }
public static Func <object> GetParameterlessConstructor(this Type type) { if (type == null) { ExThrowers.ThrowArgNull(nameof(type)); } Expression call = Expression.New(type); if (type.IsValueType) { call = Expression.Convert(call, typeof(object)); } var expr = Expression.Lambda(typeof(Func <object>), call); return((Func <object>)expr.Compile()); }
public static bool TryGetValueTupleTypes(this ParameterInfo pi, out TupleArg[] args) { if (pi == null) { ExThrowers.ThrowArgNull(nameof(pi)); } args = null; var paramType = pi.ParameterType; if (!paramType.FullName.StartsWith("System.ValueTuple`", StringComparison.Ordinal)) { return(false); } var attr = pi.GetCustomAttribute <TupleElementNamesAttribute>(); int offset = 0; args = PopulateTupleArgs(paramType, attr?.TransformNames, ref offset); return(true); }