alielie
2026-09-10 9ec80cafc23f5ee3278cacce3c9f86f4087b435a
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
111
112
113
114
115
116
117
118
119
120
121
122
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.RegularExpressions;
using DynamicExpresso.Exceptions;
using DynamicExpresso.Parsing;
 
namespace DynamicExpresso
{
    internal class ParserArguments
    {
        private readonly Dictionary<string, Parameter> _declaredParameters;
 
        private readonly HashSet<Parameter> _usedParameters = new HashSet<Parameter>();
        private readonly HashSet<ReferenceType> _usedTypes = new HashSet<ReferenceType>();
        private readonly HashSet<Identifier> _usedIdentifiers = new HashSet<Identifier>();
 
        public ParserArguments(
            string expressionText,
            ParserSettings settings,
            Type expressionReturnType,
            IEnumerable<Parameter> declaredParameters
        )
        {
            ExpressionText = expressionText;
            ExpressionReturnType = expressionReturnType;
 
            Settings = settings;
            _declaredParameters = new Dictionary<string, Parameter>(settings.KeyComparer);
            foreach (var pe in declaredParameters)
            {
                try
                {
                    _declaredParameters.Add(pe.Name, pe);
                }
                catch (ArgumentException)
                {
                    throw new DuplicateParameterException(pe.Name);
                }
            }
        }
 
        public ParserSettings Settings { get; private set; }
        public string ExpressionText { get; private set; }
        public Type ExpressionReturnType { get; private set; }
        public IEnumerable<Parameter> DeclaredParameters { get { return _declaredParameters.Values; } }
 
        public IEnumerable<Parameter> UsedParameters
        {
            get { return _usedParameters; }
        }
 
        public IEnumerable<ReferenceType> UsedTypes
        {
            get { return _usedTypes; }
        }
 
        public IEnumerable<Identifier> UsedIdentifiers
        {
            get { return _usedIdentifiers; }
        }
 
        public bool TryGetKnownType(string name, out Type type)
        {
            if (Settings.KnownTypes.TryGetValue(name, out var reference))
            {
                _usedTypes.Add(reference);
                type = reference.Type;
                return true;
            }
 
            type = null;
            return false;
        }
 
        /// <summary>
        /// Returns true if the known types contain a generic type definition with the given name + any arity (e.g. name`1).
        /// </summary>
        internal bool HasKnownGenericTypeDefinition(string name)
        {
            var regex = new Regex("^" + name + "`\\d+$");
            return Settings.KnownTypes.Values.Any(refType => regex.IsMatch(refType.Name) && refType.Type.IsGenericTypeDefinition);
        }
 
        public bool TryGetIdentifier(string name, out Expression expression)
        {
            if (Settings.Identifiers.TryGetValue(name, out var identifier))
            {
                _usedIdentifiers.Add(identifier);
                expression = identifier.Expression;
                return true;
            }
 
            expression = null;
            return false;
        }
 
        /// <summary>
        /// Get the parameter and mark is as used.
        /// </summary>
        public bool TryGetParameters(string name, out ParameterExpression expression)
        {
            if (_declaredParameters.TryGetValue(name, out var parameter))
            {
                _usedParameters.Add(parameter);
                expression = parameter.Expression;
                return true;
            }
 
            expression = null;
            return false;
        }
 
        public IEnumerable<MethodInfo> GetExtensionMethods(string methodName)
        {
            var comparer = Settings.KeyComparer;
            return Settings.ExtensionMethods.Where(p => comparer.Equals(p.Name, methodName));
        }
    }
}