/// <summary> /// crawls the given type for parameter converter methods /// </summary> /// <param name="type">the type to crawl</param> /// <param name="converters">the resulting converters</param> /// <param name="declaredConverters">the converters that are already known</param> /// <param name="methodInfos">the method infos</param> public static void CrawlConverterMethods(Type type, Dictionary <string, SpeechParameterConverter> converters, Dictionary <string, SpeechParameterConverter> declaredConverters, params MethodInfo[] methodInfos) { foreach (var methodInfo in methodInfos) { var cattributes = methodInfo.GetCustomAttributes(typeof(SpeechParameterConverterAttribute), false); if (cattributes.Length > 0) { IEnumerable <SpeechParameterConverterAttribute> speechMethodAttributes = cattributes.Cast <SpeechParameterConverterAttribute>(); //should be only one var attrib = speechMethodAttributes.FirstOrDefault(); if (attrib == null) { throw new Exception("#0 unknown"); } else { //check if its a valid method... 1 string argument, 1 return parameter ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(string) && methodInfo.ReturnType != typeof(void)) { var converter = new SpeechParameterConverter(); converter.Key = attrib.Key; converter.ExecutingType = type; converter.MethodInfo = methodInfo; if (converters.ContainsKey(converter.Key) || declaredConverters.ContainsKey(converter.Key)) { throw new Exception("the parameter converter method key: " + methodInfo.Name + " on type: " + type.FullName + " is already used by another method"); } converters.Add(converter.Key, converter); } else { throw new Exception("a parameter converter method must have 1 string parameter and returning the correct type for " + "the methods that use this converter (-> never void).\ntype: " + type.FullName + "method: " + methodInfo.Name); } } } } }
/// <summary> /// finishes the current parameter (assigns value) and if this was the last param then executes the current method /// </summary> /// <param name="valueText"></param> private bool FinishCurrentParameter(string valueText) { if (this.State == ExecutingState.ListeningForParameters) { //check the first left parameter //parameter name was left out int leftParameterIndex = -1; for (int i = 0; i < this.CurrentSpeechStream.SpeechTuple.Method.Arguments.Count; i++) { var arg = this.CurrentSpeechStream.SpeechTuple.Method.Arguments[i]; if ( this.CurrentSpeechStream.SpeechParameterStreams.Any( p => p.SpeechParameterInfo.Parameter.ParameterInfo.Name == arg.ParameterInfo.Name) == false) { leftParameterIndex = i; break; } } if (leftParameterIndex != -1) { this.CurrentParameter = new SpeechParameterStream("", this.CurrentSpeechStream.SpeechTuple, new SpeechParameterInfo(this.CurrentSpeechStream.SpeechTuple.Method.Arguments[leftParameterIndex])); } } SpeechParameterConverter converter = this.CurrentParameter.SpeechParameterInfo.Parameter.Converter; object erg = null;//OnParameterValueConvert(this.CurrentParameter, valueText); if (converter == null) { throw new Exception("converter was not set so the parameter value: " + valueText + " for parameter " + this.CurrentParameter.RecognizedParameterNameText + "(real name: " + this.CurrentParameter.SpeechParameterInfo.Parameter.ParameterInfo.Name + ") couldnt be converted"); } else { if (converter.MethodInfo.IsStatic == false && converter.InvokingInstance == null) { try { converter.InvokingInstance = Activator.CreateInstance(converter.ExecutingType); } catch (Exception ex) { throw new Exception("tried to create an instance of " + converter.ExecutingType.FullName + " in order to convert the parameter " + this.CurrentParameter.RecognizedParameterNameText + "(real name: " + this.CurrentParameter.SpeechParameterInfo.Parameter.ParameterInfo.Name + ")" + "\nException: " + ex.Message); } } erg = converter.MethodInfo.Invoke(converter.InvokingInstance, new object[] { valueText }); } if (erg != null) { this.CurrentParameter.SpeechParameterInfo.Value = erg; if (this.State == ExecutingState.ListeningForParameters) //only add if the parameter name was left out { this.CurrentSpeechStream.SpeechParameterStreams.Add(this.CurrentParameter); } this._OnParameterFinished.OnNext(this.CurrentParameter); } else { return(false); } //now check if this was the last parameter... if (this.CurrentSpeechStream.SpeechParameterStreams.Count == this.CurrentSpeechStream.SpeechTuple.Method.Arguments.Count) { //we have all parameters... if (this.CurrentSpeechStream.SpeechTuple.Method.MethodInfo.IsStatic == false) { if (this.CurrentSpeechStream.SpeechTuple.InvokeInstance == null) { var obj = Activator.CreateInstance(this.CurrentSpeechStream.SpeechTuple.Method.ExecutingType); this.CurrentSpeechStream.SpeechTuple.InvokeInstance = obj; } } //reorder parameters to fit signature var values = new List <object>(); foreach (var speechParameter in this.CurrentSpeechStream.SpeechTuple.Method.Arguments) { SpeechParameterStream speechParameterInfo = this.CurrentSpeechStream.SpeechParameterStreams.FirstOrDefault( p => p.SpeechParameterInfo.Parameter.ParameterInfo.Name == speechParameter.ParameterInfo.Name); if (speechParameterInfo != null) { values.Add(speechParameterInfo.SpeechParameterInfo.Value); } else { //TODO parameter has no value or parameter info ?? } } this._OnLastParameterFinished.OnNext(this.CurrentSpeechStream); //finally execute the method with the right parameter order ExecuteMethod(this.CurrentSpeechStream.SpeechTuple, this.CurrentSpeechStream.SpeechTuple.InvokeInstance, values.ToArray()); this.AbortListeningForParameters(); this.State = ExecutingState.ListeningForMethods; } else { this.State = ExecutingState.ListeningForParameters; } return(true); }