public void ExtractUiArtifacts(CompileTreeNode node, out IUiControl uiControl, out string label, out string iconhandle) { foreach (PropertyCompileTreeNode n in node.DefaultProperties) { if (n.Value is LayoutProducer) { LayoutProducer lp = (n.Value as LayoutProducer); uiControl = lp.UiControl; label = lp.label; iconhandle = lp.iconhandle; return; } } throw new FormCompileException("No layout defined in the source file", node.XmlSourceNodeInformation); }
private static void SetPropertyOnProducer2(ElementCompileTreeNode element, string propertyName, PropertyCompileTreeNode property, CompileContext compileContext) { if (property.Value is BaseFunctionRuntimeTreeNode && !(element.Producer is FunctionParameterProducer)) { property.Value = ((BaseFunctionRuntimeTreeNode)property.Value).GetValue(); } if (property.InclosingProducerName != "" && element.XmlSourceNodeInformation.Name != property.InclosingProducerName) { throw new FormCompileException(string.Format("The inclosing tag does not match the embedded property tag name {0}", propertyName), element, property); } Type producerType = element.Producer.GetType(); PropertyInfo propertyInfo = producerType.GetProperty(propertyName); if (propertyInfo == null) { if (property.IsNamespaceDeclaration) { return; // Ignore it } throw new FormCompileException(string.Format("The producer {0} does not have property named {1}", producerType, propertyName), element, property); } MethodInfo getMethodInfo = propertyInfo.GetGetMethod(); if (null == getMethodInfo) { throw new FormCompileException(string.Format("The producer {0} does not have a public get for the property named {1}", producerType, propertyName), element, property); } bool isReadOrBindProduced = property.Value is BindProducer || property.Value is ReadProducer; if (!isReadOrBindProduced && typeof(IDictionary).IsAssignableFrom(getMethodInfo.ReturnType)) { if (property.Value == null) { throw new FormCompileException(string.Format("Can not assign null to {0} dictionary", propertyName), element, property); } IDictionary dictionary = getMethodInfo.Invoke(element.Producer, null) as IDictionary; if (dictionary == null) { throw new InvalidOperationException(string.Format("Property '{0}' on '{1}' has not been initialized.", propertyName, producerType)); } MethodInfo dictionaryAddMethodInfo = dictionary.GetType().GetMethod("Add"); ParameterInfo[] dictionaryAddParmInfo = dictionaryAddMethodInfo.GetParameters(); Type valueType = property.Value.GetType(); if (property.Value is IDictionary) { IDictionary values = (IDictionary)property.Value; IDictionaryEnumerator dictionaryEnumerator = values.GetEnumerator(); while (dictionaryEnumerator.MoveNext()) { dictionary.Add(dictionaryEnumerator.Key, dictionaryEnumerator.Value); } } else { if (property.Value is DictionaryEntry) { var dictionaryEntry = (DictionaryEntry)property.Value; dictionary.Add(dictionaryEntry.Key, dictionaryEntry.Value); } else { PropertyInfo valueKeyProperty = valueType.GetProperty("Key"); PropertyInfo valueValueProperty = valueType.GetProperty("Value"); if (valueKeyProperty == null || valueValueProperty == null) { throw new FormCompileException(string.Format("The type {0} can not be assigned to the The parameter type {0} for the method 'Add' on the return type of the property {1} does not match the value type {2}", dictionaryAddParmInfo[0].ParameterType.ToString(), propertyName, property.Value.GetType()), element, property); } object dictionaryEntryKey = valueKeyProperty.GetGetMethod().Invoke(property.Value, null); object dictionaryEntryValue = valueValueProperty.GetGetMethod().Invoke(property.Value, null); dictionary.Add(dictionaryEntryKey, dictionaryEntryValue); } } return; } if (!isReadOrBindProduced && typeof(IList).IsAssignableFrom(getMethodInfo.ReturnType)) { IList list = getMethodInfo.Invoke(element.Producer, null) as IList; if (list == null) { throw new InvalidOperationException(string.Format("Property '{0}' (an IList) on '{1}' has not been initialized.", propertyName, producerType)); } MethodInfo listAddMethodInfo = list.GetType().GetMethod("Add"); ParameterInfo[] listAddParmInfo = listAddMethodInfo.GetParameters(); if (property.Value is IList) { IList values = (IList)property.Value; foreach (object value in values) { if (!listAddParmInfo[0].ParameterType.IsInstanceOfType(value)) { throw new FormCompileException(string.Format( "The parameter type {0} for the method 'Add' on the return type of the property {1} does not match the value type {2}", listAddParmInfo[0].ParameterType, propertyName, property.Value.GetType()), element, property); } list.Add(value); } return; } if (property.Value != null) { if (!listAddParmInfo[0].ParameterType.IsInstanceOfType(property.Value)) { throw new FormCompileException(string.Format( "The parameter type {0} for the method 'Add' on the return type of the property {1} does not match the value type {2}", listAddParmInfo[0].ParameterType, propertyName, property.Value.GetType()), element, property); } list.Add(property.Value); } return; } // Binding values for function parameters if (property.Value is ReadProducer && typeof(IList <BaseRuntimeTreeNode>).IsAssignableFrom(getMethodInfo.ReturnType)) { IList list = getMethodInfo.Invoke(element.Producer, null) as IList; object bindingObject; string source = (property.Value as ReadProducer).source; if (source.Contains(".")) { string[] parts = source.Split('.'); ResolvePropertyBinding(element, property, compileContext, parts[0], parts.Skip(1).ToArray(), out bindingObject); } else { Type bindingType; ResolveBindingObject(element, property, compileContext, source, out bindingObject, out bindingType); } list.Add(new ConstantObjectParameterRuntimeTreeNode("BindedValue", bindingObject)); return; } CheckForMultiblePropertyAdds(element, propertyName, property); MethodInfo setMethodInfo = propertyInfo.GetSetMethod(); if (null == setMethodInfo) { throw new FormCompileException(string.Format("The producer {0} does not have a public set for the property named {1}", producerType, propertyName), element, property); } object parm; if (null != property.Value) { if (property.Value is BindProducer) { object[] attributes = propertyInfo.GetCustomAttributes(typeof(BindablePropertyAttribute), true); if (attributes.Length == 0) { throw new FormCompileException(string.Format("The property {0} on the producer {1}, does not have a bind attribute specified", propertyName, producerType), element, property); } BindProducer bind = (BindProducer)property.Value; string source = bind.source; EvaluteBinding(element, source, property, compileContext, getMethodInfo, true); } else if (property.Value is ReadProducer) { ReadProducer bind = (ReadProducer)property.Value; string source = bind.source; EvaluteBinding(element, source, property, compileContext, getMethodInfo, false); } } if (property.Value != null && getMethodInfo.ReturnType.IsInstanceOfType(property.Value)) { if (typeof(IEnumerable).IsAssignableFrom(getMethodInfo.ReturnType) && getMethodInfo.ReturnType != typeof(string) && property.Value is string && ((string)property.Value).Length > 0) { // common err in form: specify a string, where a binding was expected. Problem with IEnumerable: string is converted to char array - hardly the expected result // this is not a critical, but helpful, check throw new InvalidOperationException(string.Format("Unable to cast {0} value '{1}' to type '{2}'", property.Value.GetType().FullName, property.Value, getMethodInfo.ReturnType.FullName)); } parm = property.Value; } else if (property.Value is BaseRuntimeTreeNode) { if (!(element.Producer is IFunctionProducer)) { // Handles C1 function in forms markup BaseRuntimeTreeNode baseRuntimeTreeNode = property.Value as BaseRuntimeTreeNode; object value = baseRuntimeTreeNode.GetValue(); parm = value; } else { parm = property.Value; } } else { parm = ValueTypeConverter.Convert(property.Value, getMethodInfo.ReturnType); } if (element.Producer is LayoutProducer && propertyName == "UiControl") { LayoutProducer layoutProducer = (LayoutProducer)element.Producer; if (layoutProducer.UiControl != null) { throw new FormCompileException(string.Format("Only one ui control is allow at the top level of the layout."), element, property); } } object[] parms = { parm }; setMethodInfo.Invoke(element.Producer, parms); }