// -------------------------------------------------------------------- /// <summary> /// Check the members of the array. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="Property"></param> /// <param name="ErrorString"></param> // -------------------------------------------------------------------- protected void CheckArray <T>(FactoryProperty Property, String MsgString) { T[] arrayObj = (T[])Property.Get; for (int i = 0; i < arrayObj.Length; i++) { Double val = (Double)Convert.ChangeType(arrayObj[i], typeof(Double)); if (!Double.IsNaN(Property.ParamMinVal) && val < Property.ParamMinVal) { MsgString += "The value provided for element " + i + " of parameter " + Property.FQN + " is less than its allowed minimum (" + val + " vs. " + Property.ParamMinVal + ")\n"; } if (!Double.IsNaN(Property.ParamMaxVal) && val > Property.ParamMaxVal) { MsgString += "The value provided for element " + i + " of parameter " + Property.FQN + " is greater than its allowed maximum (" + val + " vs. " + Property.ParamMaxVal + ")\n"; } } }
// -------------------------------------------------------------------- /// <summary> /// Return the type for the child node. /// </summary> /// <param name="Child"></param> /// <param name="Obj"></param> /// <returns></returns> // -------------------------------------------------------------------- private Type GetTypeOfChild(XmlNode Child, Instance Obj) { FactoryProperty Parameter = FindProperty(Child); Type t = FindType(Child.Name); if (t != null && t.BaseType != null && t.BaseType.Name == "Attribute") { t = null; // Exclude types if they are an attribute type. } if ((t == null) && (Parameter != null)) { t = CallingAssembly.GetType(Parameter.TypeName); } if ((t == null) && (Parameter != null)) { t = CallingAssembly.GetType(Obj.Name + "+" + Parameter.TypeName); } if (t == null && Obj != null && (Obj.Model.GetType().Name == "Script" || Obj.InstanceName.Contains("Script."))) { // check in the referenced assemblies. foreach (AssemblyName Reference in CallingAssembly.GetReferencedAssemblies()) { Assembly A = Assembly.Load(Reference); t = A.GetType(Child.Name); if (t != null) { return(t); } } } return(t); }
public WrapApsimType(FactoryProperty Property) { this.Property = Property; }
public WrapBuiltIn(FactoryProperty Property) { tType = typeof(T); this.Property = Property; }
// -------------------------------------------------------------------- /// <summary> /// Check for parameters in the model that haven't been given a value and throw if any /// are found. Also do range checking, if applicable. /// </summary> // -------------------------------------------------------------------- public void CheckParameters(ApsimComponent ModelInstance) { String Errors = ""; String RangeMsgs = ""; for (int i = 0; i != RegisteredProperties.Count; i++) { FactoryProperty Property = RegisteredProperties[i]; if (Property.IsParam) { if (!Property.HasAsValue && !Property.OptionalParam) { if (Errors != "") { Errors += ", "; } Errors += Property.FQN; } // Is there a tidier way to do this? if (Property.HasAsValue && (!Double.IsNaN(Property.ParamMinVal) || !Double.IsNaN(Property.ParamMaxVal))) { if (Property.TypeName == "Double" || Property.TypeName == "Single" || Property.TypeName == "Int32") { double val = Convert.ToDouble(Property.Get.ToString()); if (!Double.IsNaN(Property.ParamMinVal) && val < Property.ParamMinVal) { RangeMsgs += "The value provided for parameter " + Property.FQN + " is less than its allowed minimum (" + Property.Get.ToString() + " vs. " + Property.ParamMinVal + ")\n"; } if (!Double.IsNaN(Property.ParamMaxVal) && val > Property.ParamMaxVal) { RangeMsgs += "The value provided for parameter " + Property.FQN + " is greater than its allowed maximum (" + Property.Get.ToString() + " vs. " + Property.ParamMaxVal + ")\n"; } } else if (Property.TypeName == "Double[]") { CheckArray <double>(Property, RangeMsgs); } else if (Property.TypeName == "Single[]") { CheckArray <float>(Property, RangeMsgs); } else if (Property.TypeName == "Int32[]") { CheckArray <int>(Property, RangeMsgs); } } } } if (Errors != "") { throw new Exception("The following parameters haven't been initialised: " + Errors); } if (RangeMsgs != "") { string rangeMessage = "In " + Root.InstanceName + ", the following parameters are outside their allowable ranges:\n" + RangeMsgs; if (ModelInstance != null) { ModelInstance.Warning(rangeMessage); } else { throw new Exception(rangeMessage); } } }
// -------------------------------------------------------------------- /// <summary> /// Go through all child XML nodes for the node passed in and set /// the corresponding property values in the Obj instance passed in. /// </summary> /// <param name="Obj"></param> /// <param name="Node"></param> /// <param name="HostComponent"></param> // -------------------------------------------------------------------- private void PopulateParams(Instance Obj, XmlNode Node, ApsimComponent ParentComponent) { // Look for an XmlNode param. If found then given it our current 'Node'. bool HavePassedXMLToObj = false; foreach (FactoryProperty Property in RegisteredProperties) { if ((String.Compare(Property.TypeName, "XmlNode", StringComparison.Ordinal) == 0) && (Property.OutputName.Contains(Node.Name))) { Property.SetObject(Node); HavePassedXMLToObj = true; } } // Go through all child XML nodes for the node passed in and set // the corresponding property values in the Obj instance passed in. if (!HavePassedXMLToObj) { foreach (XmlNode Child in Node.ChildNodes) { if (Child.GetType() != typeof(XmlComment)) { Type t = GetTypeOfChild(Child, Obj); if ((t != null) && (t.IsSubclassOf(typeof(Instance)) || t.IsClass)) { // Create a child instance - indirect recursion. Instance ChildInstance = CreateInstance(Child, Child, Obj, ParentComponent); Obj.Add(ChildInstance); FactoryProperty Parameter = FindProperty(Child); if (XmlHelper.Name(Child).Contains("[")) { String ArrayName = XmlHelper.Name(Child); StringManip.SplitOffBracketedValue(ref ArrayName, '[', ']'); XmlHelper.SetName(Child, ArrayName); Parameter = FindProperty(Child); if (Parameter != null) { Parameter.AddToList(ChildInstance); } else { // Parameter must be an array link to child nodes e.g. // [Link] LeafCohort[] InitialLeaves; } } else if ((Parameter != null) && (Parameter.IsParam && !Parameter.TypeName.Contains("System::"))) { Parameter.SetObject(ChildInstance.Model); } } else if (Child.Name == "Memo") { // Ignore memo fields. } else { FactoryProperty Parameter = FindProperty(Child); if (Parameter != null) { Parameter.Name = XmlHelper.Name(Child); Parameter.Set(Child); } } } } } }
// -------------------------------------------------------------------- /// <summary> /// Go through all reflected fields and properties that are tagged /// with a 'Param' or 'Input' attribute and add them to our list /// of registered properties. /// </summary> /// <param name="Obj"></param> /// <param name="Parent"></param> // -------------------------------------------------------------------- private void GetAllProperties(Instance Obj, XmlNode Parent) { FieldInfo[] fields = Obj.Model.GetType().GetFields(BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo Property in fields) { bool AddProperty = false; bool IsOutput = false; Object[] Attributes = Property.GetCustomAttributes(false); foreach (Object Attr in Attributes) { Type attrType = Attr.GetType(); IsOutput = (IsOutput || (Attr.GetType() == typeof(Output))); if (attrType == typeof(Param)) { AddProperty = true; } if (attrType == typeof(Input)) { AddProperty = true; } if (attrType == typeof(Writable)) { AddProperty = true; } if (attrType == typeof(Output)) { AddProperty = true; } if (attrType == typeof(Link)) { LinkField LinkF = new LinkField(Obj, Property, (Link)Attr); Links.Add(LinkF); } } if (AddProperty) { FactoryProperty NewProperty = new FactoryProperty(new ReflectedField(Property, Obj.Model), Parent); if (IsOutput) { RemoveRegisteredOutput(NewProperty.OutputName); } RegisteredProperties.Add(NewProperty); } } PropertyInfo[] properties = Obj.Model.GetType().GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo Property in properties) { bool AddProperty = false; bool IsOutput = false; Object[] Attributes = Property.GetCustomAttributes(false); foreach (Object Attr in Attributes) { IsOutput = (IsOutput || (Attr.GetType() == typeof(Output))); if (Attr.GetType() == typeof(Param)) { AddProperty = true; } if (Attr.GetType() == typeof(Input)) { AddProperty = true; } if (Attr.GetType() == typeof(Writable)) { AddProperty = true; } if (Attr.GetType() == typeof(Output)) { AddProperty = true; } if (Attr.GetType() == typeof(Link)) { LinkField LinkF = new LinkField(Obj, Property, (Link)Attr); Links.Add(LinkF); } } if (AddProperty) { if ((String.Compare(Property.PropertyType.Name, "String") == 0) || Property.PropertyType.IsValueType || Property.PropertyType.IsArray || Property.PropertyType.GetInterface("ApsimType") != null) { FactoryProperty NewProperty = new FactoryProperty(new ReflectedProperty(Property, Obj.Model), Parent); if (IsOutput) { RemoveRegisteredOutput(NewProperty.OutputName); } RegisteredProperties.Add(NewProperty); } } } }