| 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(); | 
|         } | 
|     } | 
| } |