/// <summary> /// Determine penalty for mismatched arguments (- is penalty and + is a reward) /// </summary> /// <returns> /// The penalty. /// </returns> /// <param name='paramclass'> /// parameter class. /// </param> /// <param name='argclass'> /// class of given argument. /// </param> internal static int ArgumentPenalty(Type paramclass, Type argclass) { if (typeof(Vector <double>).IsAssignableFrom(paramclass)) { if (typeof(Vector <double>).IsAssignableFrom(argclass)) { return(100); } if (argclass == typeof(double) || argclass == typeof(int)) { return(50); } else { return(-100); } } if (paramclass == typeof(string) && argclass == null) { return(100); } if (!paramclass.IsValueType && argclass == null) { return(100); } if (paramclass.IsArray && paramclass.GetElementType() == argclass) { return(10); } if (!paramclass.IsValueType) { return(-100); } var paramtype = ValueTypeUtils.TypeOf(paramclass); var argtype = ValueTypeUtils.TypeOf(argclass); if (paramtype == argtype && paramtype != VType.Other) { return(100); } switch (paramtype) { case VType.Short: switch (argtype) { case VType.Int: case VType.Long: return(50); case VType.Float: case VType.Double: return(20); default: return(-50); } case VType.Int: switch (argtype) { case VType.Long: return(50); case VType.Short: case VType.Float: case VType.Double: return(75); default: return(-50); } case VType.Long: switch (argtype) { case VType.Short: case VType.Int: case VType.Float: case VType.Double: return(50); default: return(-50); } case VType.Float: switch (argtype) { case VType.Float: case VType.Double: return(100); case VType.Long: return(20); case VType.Short: case VType.Int: return(50); default: return(-50); } case VType.Double: switch (argtype) { case VType.Int: case VType.Short: case VType.Long: return(50); case VType.Float: case VType.Double: return(100); default: return(-50); } case VType.Bool: switch (argtype) { case VType.Long: case VType.Float: case VType.Double: return(20); case VType.Int: case VType.Short: case VType.Byte: case VType.Char: return(50); default: return(-50); case VType.Enum: switch (argtype) { case VType.Int: return(50); case VType.String: return(100); default: return(-50); } } } if (paramclass == typeof(ZDateTime)) { if (argclass == typeof(string)) { return(20); } if (argclass == typeof(long)) { return(50); } else { return(-50); } } return(-100); }
/// <summary> /// Convert arguments to parameter types where they mismatch /// </summary> /// <param name='ctor'> /// Ctor. /// </param> /// <param name='args'> /// Arguments. /// </param> public static void ConformArguments(ParameterInfo[] paramlist, object[] args) { int i = -1; foreach (var parm in paramlist) { i++; object arg = args[i]; Type pclass = parm.ParameterType; Type aclass = arg != null?arg.GetType() : null; var ptype = ValueTypeUtils.TypeOf(pclass); var atype = ValueTypeUtils.TypeOf(aclass); if ((atype == ptype && atype != VType.Other) || pclass == aclass || pclass.IsAssignableFrom(aclass)) { continue; } if (arg == null && pclass.IsValueType) { throw new ArgumentException("could not find matching constructor"); } if (arg == null) { continue; } // convert simple value types to conform if (ptype != VType.Other) { args[i] = ValueTypeUtils.Convert(arg, ptype, pclass); } // special handling for delegates else if (DelegateGenerator.IsDelegate(pclass)) { args[i] = DelegateGenerator.ConvertToDelegate(pclass, args[i]); } // special case for ZDateTime, allowing long specifier else if (pclass == typeof(ZDateTime)) { if (aclass == typeof(long)) { args[i] = new ZDateTime((long)arg, ZTimeZone.NewYork); } else if (aclass == typeof(string)) { args[i] = new ZDateTime((string)arg); } else { throw new ArgumentException("unknown argument pairing"); } } // see if we can instantiate a persitable class else if (atype == VType.String && pclass.IsSubclassOf(typeof(IPersist <string>))) { var nobj = (IPersist <string>)Activator.CreateInstance(pclass); nobj.State = (string)arg; args[i] = nobj; } // the parameter type is an array, but our value is a single value of the same type, convert else if (pclass.IsArray && pclass.GetElementType() == aclass) { var narray = Array.CreateInstance(pclass.GetElementType(), 1); narray.SetValue(arg, 0); args[i] = narray; } else if (typeof(Vector <double>).IsAssignableFrom(pclass)) { if (aclass == typeof(double)) { var vec = new DenseVector(1); vec[0] = ((Double)args[i]); args[i] = vec; } if (aclass == typeof(int)) { var vec = new DenseVector(1); vec[0] = (double)((Int32)args[i]); args[i] = vec; } } // otherwise try to create a new instance from string else if (atype == VType.String) { string sval = (string)arg; try { var method = pclass.GetMethod("Parse"); if (method != null) { args[i] = method.Invoke(null, new object[] { sval }); continue; } } catch { } try { args[i] = Activator.CreateInstance(pclass, sval); } catch { throw new ArgumentException("could not coerce type " + aclass + " to " + pclass); } } } }