public override void Validate(object state) { base.Validate(state); //if (XPath.IsNull()) // throw new ChoRecordConfigurationException("XPath can't be null or whitespace."); if (XPath.IsNullOrWhiteSpace()) { if (!IsDynamicObject && (RecordType.IsGenericType && RecordType.GetGenericTypeDefinition() == typeof(KeyValuePair <,>))) { NodeName = NodeName.IsNullOrWhiteSpace() ? "KeyValuePair" : NodeName; RootName = RootName.IsNullOrWhiteSpace() ? "KeyValuePairs" : RootName; } else if (!IsDynamicObject && !typeof(IChoScalarObject).IsAssignableFrom(RecordType)) { NodeName = NodeName.IsNullOrWhiteSpace() ? RecordType.Name : NodeName; RootName = RootName.IsNullOrWhiteSpace() ? NodeName.ToPlural() : RootName; } } else { RootName = RootName.IsNullOrWhiteSpace() ? XPath.SplitNTrim("/").Where(t => !t.IsNullOrWhiteSpace() && t.NTrim() != "." && t.NTrim() != ".." && t.NTrim() != "*").FirstOrDefault() : RootName; NodeName = NodeName.IsNullOrWhiteSpace() ? XPath.SplitNTrim("/").Where(t => !t.IsNullOrWhiteSpace() && t.NTrim() != "." && t.NTrim() != ".." && t.NTrim() != "*").Skip(1).FirstOrDefault() : NodeName; } string rootName = null; string nodeName = null; ChoXmlDocumentRootAttribute da = TypeDescriptor.GetAttributes(RecordType).OfType <ChoXmlDocumentRootAttribute>().FirstOrDefault(); if (da != null) { rootName = da.Name; } else { XmlRootAttribute ra = TypeDescriptor.GetAttributes(RecordType).OfType <XmlRootAttribute>().FirstOrDefault(); if (ra != null) { nodeName = ra.ElementName; } } RootName = RootName.IsNullOrWhiteSpace() && !rootName.IsNullOrWhiteSpace() ? rootName : RootName; NodeName = NodeName.IsNullOrWhiteSpace() && !nodeName.IsNullOrWhiteSpace() ? nodeName : NodeName; RootName = RootName.IsNullOrWhiteSpace() && !NodeName.IsNullOrWhiteSpace() ? NodeName.ToPlural() : RootName; if (!RootName.IsNullOrWhiteSpace() && RootName.ToSingular() != RootName) { NodeName = NodeName.IsNullOrWhiteSpace() && !RootName.IsNullOrWhiteSpace() ? RootName.ToSingular() : NodeName; } if (RootName.IsNullOrWhiteSpace()) { RootName = "Root"; } if (NodeName.IsNullOrWhiteSpace()) { NodeName = "XElement"; } //Encode Root and node names RootName = System.Net.WebUtility.HtmlEncode(RootName); NodeName = System.Net.WebUtility.HtmlEncode(NodeName); string[] fieldNames = null; XElement xpr = null; if (state is Tuple <long, XElement> ) { xpr = ((Tuple <long, XElement>)state).Item2; } else { fieldNames = state as string[]; } if (AutoDiscoverColumns && XmlRecordFieldConfigurations.Count == 0) { if (RecordType != null && !IsDynamicObject && ChoTypeDescriptor.GetProperties(RecordType).Where(pd => pd.Attributes.OfType <ChoXmlNodeRecordFieldAttribute>().Any()).Any()) { DiscoverRecordFields(RecordType); } else if (xpr != null) { XmlRecordFieldConfigurations.AddRange(DiscoverRecordFieldsFromXElement(xpr)); } else if (!fieldNames.IsNullOrEmpty()) { foreach (string fn in fieldNames) { if (IgnoredFields.Contains(fn)) { continue; } if (fn.StartsWith("_")) { string fn1 = fn.Substring(1); var obj = new ChoXmlRecordFieldConfiguration(fn, xPath: $"./{fn1}"); obj.FieldName = fn1; obj.IsXmlAttribute = true; XmlRecordFieldConfigurations.Add(obj); } else if (fn.EndsWith("_")) { string fn1 = fn.Substring(0, fn.Length - 1); var obj = new ChoXmlRecordFieldConfiguration(fn, xPath: $"./{fn1}"); obj.FieldName = fn1; obj.IsXmlCDATA = true; XmlRecordFieldConfigurations.Add(obj); } else { var obj = new ChoXmlRecordFieldConfiguration(fn, xPath: $"./{fn}"); XmlRecordFieldConfigurations.Add(obj); } } } } else { IsComplexXPathUsed = false; foreach (var fc in XmlRecordFieldConfigurations) { if (fc.IsArray == null) { fc.IsArray = typeof(ICollection).IsAssignableFrom(fc.FieldType); } if (fc.FieldName.IsNullOrWhiteSpace()) { fc.FieldName = fc.Name; } if (fc.XPath.IsNullOrWhiteSpace()) { fc.XPath = $"/{fc.FieldName}|/@{fc.FieldName}"; } else { if (fc.XPath == fc.FieldName || fc.XPath == $"/{fc.FieldName}" || fc.XPath == $"/{fc.FieldName}" || fc.XPath == $"/{fc.FieldName}" || fc.XPath == $"/@{fc.FieldName}" || fc.XPath == $"/@{fc.FieldName}" || fc.XPath == $"/@{fc.FieldName}" ) { } else { IsComplexXPathUsed = true; fc.UseCache = false; } } } } if (XmlRecordFieldConfigurations.Count <= 0) { throw new ChoRecordConfigurationException("No record fields specified."); } //Validate each record field foreach (var fieldConfig in XmlRecordFieldConfigurations) { fieldConfig.Validate(this); } //Check field position for duplicate string[] dupFields = XmlRecordFieldConfigurations.GroupBy(i => i.Name) .Where(g => g.Count() > 1) .Select(g => g.Key).ToArray(); if (dupFields.Length > 0) { throw new ChoRecordConfigurationException("Duplicate field(s) [Name(s): {0}] found.".FormatString(String.Join(",", dupFields))); } PIDict = new Dictionary <string, System.Reflection.PropertyInfo>(); PDDict = new Dictionary <string, PropertyDescriptor>(); foreach (var fc in XmlRecordFieldConfigurations) { var pd1 = fc.DeclaringMember.IsNullOrWhiteSpace() ? ChoTypeDescriptor.GetProperty(RecordType, fc.Name) : ChoTypeDescriptor.GetProperty(RecordType, fc.DeclaringMember); if (pd1 != null) { fc.PropertyDescriptor = pd1; } if (fc.PropertyDescriptor == null) { fc.PropertyDescriptor = TypeDescriptor.GetProperties(RecordType).AsTypedEnumerable <PropertyDescriptor>().Where(pd => pd.Name == fc.Name).FirstOrDefault(); } if (fc.PropertyDescriptor == null) { continue; } PIDict.Add(fc.Name, fc.PropertyDescriptor.ComponentType.GetProperty(fc.PropertyDescriptor.Name)); PDDict.Add(fc.Name, fc.PropertyDescriptor); } RecordFieldConfigurationsDict = XmlRecordFieldConfigurations.OrderBy(c => c.IsXmlAttribute).Where(i => !i.Name.IsNullOrWhiteSpace()).ToDictionary(i => i.Name); if (XmlRecordFieldConfigurations.Where(e => e.IsNullable).Any() || NullValueHandling == ChoNullValueHandling.Default) { if (NamespaceManager != null) { if (!NamespaceManager.HasNamespace("xsi")) { NamespaceManager.AddNamespace("xsi", ChoXmlSettings.XmlSchemaInstanceNamespace); } if (!NamespaceManager.HasNamespace("xsd")) { NamespaceManager.AddNamespace("xsd", ChoXmlSettings.XmlSchemaNamespace); } } } LoadNCacheMembers(XmlRecordFieldConfigurations); }