hch
2025-09-03 f27e132391f11de7a199d27a32c142f41d002295
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections;
using Jace.Util;
 
namespace Jace.Execution
{
    public class FunctionRegistry : IFunctionRegistry
    {
        private const string DynamicFuncName = "Jace.DynamicFunc";
 
        private readonly bool caseSensitive;
        private readonly Dictionary<string, FunctionInfo> functions;
 
        public FunctionRegistry(bool caseSensitive)
        {
            this.caseSensitive = caseSensitive;
            this.functions = new Dictionary<string, FunctionInfo>();
        }
 
        public IEnumerator<FunctionInfo> GetEnumerator()
        {
            return functions.Values.GetEnumerator();
        }
 
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
 
        public FunctionInfo GetFunctionInfo(string functionName)
        {
            if (string.IsNullOrEmpty(functionName))
                throw new ArgumentNullException("functionName");
 
            FunctionInfo functionInfo = null;
            return functions.TryGetValue(ConvertFunctionName(functionName), out functionInfo) ? functionInfo : null;
        }
 
        public void RegisterFunction(string functionName, Delegate function)
        {
            RegisterFunction(functionName, function, true, true);
        }
        
        public void RegisterFunction(string functionName, Delegate function, bool isIdempotent, bool isOverWritable)
        {
            if (string.IsNullOrEmpty(functionName))
                throw new ArgumentNullException("functionName");
 
            if (function == null)
                throw new ArgumentNullException("function");
 
            Type funcType = function.GetType();
            bool isDynamicFunc = false;
            int numberOfParameters = -1;
            
            if (funcType.FullName.StartsWith("System.Func"))
            {
                foreach (Type genericArgument in funcType.GenericTypeArguments)
                    if (genericArgument != typeof(double))
                        throw new ArgumentException("Only doubles are supported as function arguments.", "function");
 
                numberOfParameters = function
                    .GetMethodInfo()
                    .GetParameters()
                    .Count(p => p.ParameterType == typeof(double));
            }
            else if (funcType.FullName.StartsWith(DynamicFuncName))
            {
                isDynamicFunc = true;
            }
            else
                throw new ArgumentException("Only System.Func and " + DynamicFuncName + " delegates are permitted.", "function");
 
            functionName = ConvertFunctionName(functionName);
 
            if (functions.ContainsKey(functionName) && !functions[functionName].IsOverWritable)
            {
                string message = string.Format("The function \"{0}\" cannot be overwriten.", functionName);
                throw new Exception(message);
            }
 
            if (functions.ContainsKey(functionName) && functions[functionName].NumberOfParameters != numberOfParameters)
            {
                string message = string.Format("The number of parameters cannot be changed when overwriting a method.");
                throw new Exception(message);
            }
 
            if (functions.ContainsKey(functionName) && functions[functionName].IsDynamicFunc != isDynamicFunc)
            {
                string message = string.Format("A Func can only be overwritten by another Func and a DynamicFunc can only be overwritten by another DynamicFunc.");
                throw new Exception(message);
            }
 
            FunctionInfo functionInfo = new FunctionInfo(functionName, numberOfParameters, isIdempotent, isOverWritable, isDynamicFunc, function);
 
            if (functions.ContainsKey(functionName))
                functions[functionName] = functionInfo;
            else
                functions.Add(functionName, functionInfo);
        }
 
            public bool IsFunctionName(string functionName)
        {
            if (string.IsNullOrEmpty(functionName))
                throw new ArgumentNullException("functionName");
 
            return functions.ContainsKey(ConvertFunctionName(functionName));
        }
 
        private string ConvertFunctionName(string functionName)
        {
            return caseSensitive ? functionName : functionName.ToLowerFast();
        }
    }
}