alielie
2026-09-10 f3889f2d36c50cf99468594854def9b7ed069fb5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
 
namespace DynamicExpresso.Reflection
{
    internal static class ReflectionExtensions
    {
        public static readonly MethodInfo StringConcatMethod = GetStringConcatMethod();
        public static readonly MethodInfo ObjectToStringMethod = GetObjectToStringMethod();
 
        public static DelegateInfo GetDelegateInfo(Type delegateType, params string[] parametersNames)
        {
            var method = delegateType.GetMethod("Invoke");
            if (method == null)
                throw new ArgumentException("The specified type is not a delegate");
 
            var delegateParameters = method.GetParameters();
            var parameters = new Parameter[delegateParameters.Length];
 
            var useCustomNames = parametersNames != null && parametersNames.Length > 0;
 
            if (useCustomNames && parametersNames.Length != parameters.Length)
                throw new ArgumentException(string.Format("Provided parameters names doesn't match delegate parameters, {0} parameters expected.", parameters.Length));
 
            for (var i = 0; i < parameters.Length; i++)
            {
                var paramName = useCustomNames ? parametersNames[i] : delegateParameters[i].Name;
                var paramType = delegateParameters[i].ParameterType;
 
                parameters[i] = new Parameter(paramName, paramType);
            }
 
            return new DelegateInfo(method.ReturnType, parameters);
        }
 
        public static IEnumerable<MethodInfo> GetExtensionMethods(Type type)
        {
            if (type.IsSealed && type.IsAbstract && !type.IsGenericType && !type.IsNested)
            {
                var query = from method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
                            where method.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), false)
                            select method;
                return query;
            }
 
            return Enumerable.Empty<MethodInfo>();
        }
 
        public class DelegateInfo
        {
            public DelegateInfo(Type returnType, Parameter[] parameters)
            {
                ReturnType = returnType;
                Parameters = parameters;
            }
 
            public Type ReturnType { get; private set; }
            public Parameter[] Parameters { get; private set; }
        }
 
        private static MethodInfo GetStringConcatMethod()
        {
            var methodInfo = typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string) });
            if (methodInfo == null)
            {
                throw new Exception("String concat method not found");
            }
 
            return methodInfo;
        }
 
        private static MethodInfo GetObjectToStringMethod()
        {
            var toStringMethod = typeof(object).GetMethod("ToString", Type.EmptyTypes);
            if (toStringMethod == null)
            {
                throw new Exception("ToString method not found");
            }
 
            return toStringMethod;
        }
 
        public static Type GetFuncType(int parameterCount)
        {
            // +1 for the return type
            return typeof(Func<>).Assembly.GetType($"System.Func`{parameterCount + 1}");
        }
 
        public static Type GetActionType(int parameterCount)
        {
            return typeof(Action<>).Assembly.GetType($"System.Action`{parameterCount}");
        }
 
        public static bool HasParamsArrayType(ParameterInfo parameterInfo)
        {
            return parameterInfo.IsDefined(typeof(ParamArrayAttribute), false);
        }
 
        public static Type GetParameterType(ParameterInfo parameterInfo)
        {
            var isParamsArray = HasParamsArrayType(parameterInfo);
            var type = isParamsArray
                ? parameterInfo.ParameterType.GetElementType()
                : parameterInfo.ParameterType;
            return type;
        }
    }
}