Пример #1
0
        public static ValueTupleGetValuesInvoker ValueTupleValuesGetter(this Type type)
        {
            lock (getterLock)
            {
                return(getters.GetOrSet(type, () =>
                {
                    if (!type.IsGenericType || !type.Name.StartsWith("ValueTuple`"))
                    {
                        ExThrowers.ThrowArgEx($"{nameof(type)} is not ValueTuple type");
                    }
                    var fields = type.GetFields();

                    var instParam = Expression.Parameter(typeof(object), "instance");
                    var instVT = Expression.Convert(instParam, type);

                    var fieldExpressions = fields.Select((f, i) =>
                    {
                        Expression fieldExpr = Expression.Field(instVT, f);
                        if (f.FieldType == typeof(object))
                        {
                            return fieldExpr;
                        }
                        return Expression.Convert(fieldExpr, typeof(object));
                    });
                    var arrayExpr = Expression.NewArrayInit(typeof(object), fieldExpressions.ToArray());
                    var expr = Expression.Lambda(typeof(ValueTupleGetValuesInvoker), arrayExpr, instParam);
                    return (ValueTupleGetValuesInvoker)expr.Compile();
                }));
            }
        }
Пример #2
0
        public static MemberGetterIndexed DelegateForGetPropertyIndex(this PropertyInfo p)
        {
            var idxParams = p.GetIndexParameters();

            if (idxParams.Length != 1)
            {
                ExThrowers.ThrowArgEx("Property is not index type");
            }
            var parentType = p.DeclaringType;
            var m          = p.GetMethod;
            var type       = p.PropertyType;
            var idxType    = idxParams[0].ParameterType;

            var instParam     = Expression.Parameter(typeof(object), "instance");
            var idxParam      = Expression.Parameter(typeof(object), "index");
            var callInstParam = m.IsStatic ? null :
                                ((parentType == typeof(object)) ? (Expression)instParam : Expression.Convert(instParam, parentType));
            var callIdxParam = (idxType == typeof(object)) ? (Expression)idxParam : Expression.Convert(idxParam, idxType);

            var call = Expression.Call(callInstParam, m, callIdxParam);
            var body = type.IsValueType ? (Expression)Expression.Convert(call, typeof(object)) : call;
            var expr = Expression.Lambda(typeof(MemberGetterIndexed), body, instParam, idxParam);

            return((MemberGetterIndexed)expr.Compile());
        }
Пример #3
0
        public static MemberGetterIndexed <T> DelegateForGetPropertyIndex <T>(this PropertyInfo p)
        {
            var idxParams = p.GetIndexParameters();

            if (idxParams.Length != 1)
            {
                ExThrowers.ThrowArgEx("Property is not index type");
            }
            var parentType = p.DeclaringType;
            var m          = p.GetMethod;
            var type       = p.PropertyType;
            var idxType    = idxParams[0].ParameterType;
            var genType    = typeof(T);

            if (!genType.IsAssignableFrom(type))
            {
                ExThrowers.ThrowArgEx($"Generic argument ({genType}) cannot be assigned from property type ({type})");
            }

            var instParam     = Expression.Parameter(typeof(object), "instance");
            var idxParam      = Expression.Parameter(typeof(object), "index");
            var callInstParam = m.IsStatic ? null :
                                ((parentType == typeof(object)) ? (Expression)instParam : Expression.Convert(instParam, parentType));
            var callIdxParam = (idxType == typeof(object)) ? (Expression)idxParam : Expression.Convert(idxParam, idxType);

            var call = Expression.Call(callInstParam, m, callIdxParam);
            var body = type.IsValueType ? (Expression)Expression.Convert(call, genType) : call;
            var expr = Expression.Lambda(typeof(MemberGetterIndexed <T>), body, instParam, idxParam);

            return((MemberGetterIndexed <T>)expr.Compile());
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
 public static Type AsValueTupleType(this Type[] types)
 {
     types.ThrowIfNull(nameof(types));
     if (types.Length < 1)
     {
         ExThrowers.ThrowArgEx("Unable to create ValueTuple with less than one type");
     }
     if (types.Length > creatorsConstructorCache.Length)
     {
         ExThrowers.ThrowArgEx($"Unable to create ValueTuple type with more than {valueTupleTypes.Length} args");
     }
     return(valueTupleTypes[types.Length - 1].MakeGenericType(types));
 }
Пример #7
0
 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);
 }
Пример #8
0
        public static ConstructorInvoker AsValueTupleCreator(this Type[] types)
        {
            types.ThrowIfNull(nameof(types));
            if (types.Length >= creatorsConstructorCache.Length)
            {
                ExThrowers.ThrowArgEx($"Unable to create ValueTuple type with more than {creatorsConstructorCache.Length} args");
            }

            return(creators.GetOrAdd(types, t =>
            {
                var invoker = creatorsConstructorCache[t.Length].MakeGenericMethod(t).DelegateForMethod();
                return objs => invoker(null, objs);
            }));
        }
Пример #9
0
        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 ConstructorInvoker <T> DelegateForConstructor <T>(this ConstructorInfo c)
        {
            var parentType = c.DeclaringType;

            if (!typeof(T).IsAssignableFrom(parentType))
            {
                ExThrowers.ThrowArgEx($"Can't assign parent type ({parentType}) to T ({typeof(T)})");
            }

            var ctorParams = c.GetParameters().Select(p => p.ParameterType).ToArray();

            var argsParam = Expression.Parameter(typeof(object[]), "args");

            var indexedParams = ctorParams.Select((arg, i) =>
            {
                Expression argExpr = Expression.ArrayAccess(argsParam, Expression.Constant(i));
                if (arg == typeof(object))
                {
                    return(argExpr);
                }
                return(Expression.Convert(argExpr, arg));
            }).ToArray();

            Expression createInst;

            if (ctorParams.Length > 0)
            {
                createInst = Expression.New(c, indexedParams);
            }
            else
            {
                createInst = Expression.New(c);
            }

            Expression <Action <object[]> > callArgEx = a => ExThrowers.ThrowArgEx($"Number of supplied arguments ({a.Length}) does not match number of constructor arguments ({ctorParams.Length})");
            var checkerExpr = Expression.IfThen(Expression.NotEqual(Expression.ArrayLength(argsParam), Expression.Constant(ctorParams.Length)),
                                                Expression.Invoke(callArgEx, argsParam));

            createInst = Expression.Block(checkerExpr, createInst);

            if (parentType.IsValueType)
            {
                createInst = Expression.Convert(createInst, typeof(T));
            }

            var expr = Expression.Lambda(typeof(ConstructorInvoker <T>), createInst, argsParam);

            return((ConstructorInvoker <T>)expr.Compile());
        }
Пример #11
0
        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);
        }
Пример #13
0
        public static MemberGetterIndexed GetMemberGetterDelegate(this Type arrayType)
        {
            if (!arrayType.IsArray)
            {
                ExThrowers.ThrowArgEx($"{nameof(arrayType)} is not an array");
            }
            var elementType = arrayType.GetElementType();

            var instParam = Expression.Parameter(typeof(object), "instance");
            var idxParam  = Expression.Parameter(typeof(object), "index");

            var callInstParam = Expression.Convert(instParam, arrayType);
            var callIdxParam  = Expression.Convert(idxParam, typeof(int));
            var arrayIndex    = Expression.ArrayIndex(callInstParam, callIdxParam);
            var body          = elementType.IsValueType ? (Expression)Expression.Convert(arrayIndex, typeof(object)) : arrayIndex;
            var expr          = Expression.Lambda(typeof(MemberGetterIndexed), body, instParam, idxParam);

            return((MemberGetterIndexed)expr.Compile());
        }
Пример #14
0
 public static TDelegate CallForType(Type specialised, Type specialisedClass, string specialisedMethodName)
 {
     return(creatorCache.GetOrAdd(specialised, _ =>
     {
         if (!typeof(Delegate).IsAssignableFrom(typeof(TDelegate)))
         {
             ExThrowers.ThrowArgEx($"{nameof(TDelegate)} is not a delegate");
         }
         if (!specialisedClass.IsGenericType)
         {
             ExThrowers.ThrowArgEx($"{nameof(specialisedClass)} is not a generic type type");
         }
         if (specialisedClass.IsConstructedGenericType)
         {
             ExThrowers.ThrowArgEx($"{nameof(specialisedClass)} must be a non-constructed generic type");
         }
         var callArgs = typeof(TDelegate).GetMethod("Invoke").GetParameters().Select(p => p.ParameterType).ToArray();
         return specialisedClass.MakeGenericType(specialised).GetMethod(specialisedMethodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, null, callArgs, null).CreateCustomDelegate <TDelegate>();
     }));
 }
        public static Func <object> DelegateForConstructorNoArgs(this ConstructorInfo c)
        {
            var parentType = c.DeclaringType;

            if (c.GetParameters().Length > 0)
            {
                ExThrowers.ThrowArgEx("This method is only for constructors with no arguments");
            }

            Expression call = Expression.New(c);

            if (parentType.IsValueType)
            {
                call = Expression.Convert(call, typeof(object));
            }

            var expr = Expression.Lambda(typeof(Func <object>), call);

            return((Func <object>)expr.Compile());
        }
Пример #16
0
        static Type TaskType(Task task)
        {
            var genTask = task.GetType();

            for (; ;)
            {
                if (genTask == typeof(Task))
                {
                    ExThrowers.ThrowArgEx("task does not have Result");
                }
                if (genTask.IsGenericType)
                {
                    var t = genTask.GetGenericTypeDefinition();
                    if (t == typeof(Task <>))
                    {
                        break;
                    }
                }
                genTask = genTask.BaseType;
            }
            return(genTask.GetGenericArguments()[0]);
        }
Пример #17
0
 public static async Task <T> TimeoutAfter <T>(this Task <T> task, TimeSpan timeout)
 {
     if (timeout == TimeSpan.MaxValue)
     {
         return(await task);
     }
     if (timeout == TimeSpan.Zero)
     {
         ExThrowers.ThrowTimeoutEx();
         return(await task); // will never get here
     }
     using (var timeoutCancellationTokenSource = new CancellationTokenSource())
     {
         if (task == await Task.WhenAny(task, Task.Delay(timeout, timeoutCancellationTokenSource.Token)))
         {
             timeoutCancellationTokenSource.Cancel();
         }
         else
         {
             ExThrowers.ThrowTimeoutEx();
         }
         return(await task);
     }
 }
        public static Func <T> DelegateForConstructorNoArgs <T>(this ConstructorInfo c)
        {
            var parentType = c.DeclaringType;

            if (!typeof(T).IsAssignableFrom(parentType))
            {
                ExThrowers.ThrowArgEx($"Can't assign parent type ({parentType}) to T ({typeof(T)})");
            }
            if (c.GetParameters().Length > 0)
            {
                ExThrowers.ThrowArgEx("This method is only for constructors with no arguments");
            }

            Expression call = Expression.New(c);

            if (parentType.IsValueType)
            {
                call = Expression.Convert(call, typeof(T));
            }

            var expr = Expression.Lambda(typeof(Func <T>), call);

            return((Func <T>)expr.Compile());
        }