public IEnumerable <XElement> GetReferencedXElements(IQueryable <SOURCE> sourceTypeIqueryable, List <string> destinationPropertyNames, XName elementName, string propertyNamePrefix) { IQueryable <DEST> data = GetReferencedQueryable(sourceTypeIqueryable); Expression <Func <DEST, XElement> > xelementSelector = XElementSelectHelper <DEST> .BuildXElementSelector(destinationPropertyNames, elementName, propertyNamePrefix); return(data.Select(xelementSelector)); }
public static IEnumerable <XElement> GetXElements( Expression <Func <T, bool> > filter, LambdaExpression orderBy, bool orderAscending, int coreElementItemsPerPage, int coreElementPageNumber, IEnumerable <string> propertyNames, XNamespace elementNamespace, string elementNameString, bool showReferencesInline, bool showPagingInfo, bool randomized) { List <string> propertyNameList = new List <string>(propertyNames); List <string> autoAppendedPropertyNames = new List <string>(); List <string> referencedIdAttrubuteNames = new List <string>(); XName coreElementName = elementNamespace + elementNameString; Dictionary <string, List <string> > referencesLookup = new Dictionary <string, List <string> >(); foreach (string referencePropertyName in propertyNameList.Where(f => f.Contains("."))) { string[] referenceElements = referencePropertyName.Split('.'); if (referenceElements.Length != 2) { throw new InvalidOperationException(string.Format("Property names with a dot must have exactly one dot - failed to parse '{0}'", referencePropertyName)); } if (referencesLookup.ContainsKey(referenceElements[0]) == false) { referencesLookup.Add(referenceElements[0], new List <string>()); } referencesLookup[referenceElements[0]].Add(referenceElements[1]); } // rewrite with linq if (showReferencesInline) { // Ensure keys are included foreach (string referencePropertyName in referencesLookup.Keys) { if (propertyNameList.Contains(referencePropertyName) == false) { propertyNameList.Add(referencePropertyName); autoAppendedPropertyNames.Add(referencePropertyName); } } } var result = new List <XElement>(); Expression <Func <T, XElement> > xelementSelector = XElementSelectHelper <T> .BuildXElementSelector(propertyNameList.Where(f => f.IndexOf('.') == -1).ToList(), coreElementName); // TODO: handle case of the default sorting (by predicate element => true) IOrderByTypeFixer <T> orderByTypeFixer = GetOrderByTypeFixer(orderBy); IQueryable <T> coreDataItems = orderByTypeFixer.GetCastedIQueryable(filter, orderBy, orderAscending, coreElementItemsPerPage, coreElementPageNumber, randomized); if (randomized && referencesLookup.Any()) { // performance hit! make elegant when time permits. coreDataItems = coreDataItems.ToList().AsQueryable(); } // Perf. optimization if (coreDataItems.IsEnumerableQuery()) { Func <T, XElement> compiledExpression = XElementSelectHelper <T> .GetCompiledFunction(xelementSelector); result.AddRange(Enumerable.Select(coreDataItems, compiledExpression)); } else { result.AddRange(coreDataItems.Select(xelementSelector)); } var referencedResults = new List <XElement>(); // int referencedCoreElementCount = (orderByIsDeterministic ? coreElementItemsPerPage : int.MaxValue); foreach (string referencePropertyName in referencesLookup.Keys) { IReferencedDataHelper <T> fixer = ReferencedDataHelperBuilder <T> .Build(referencePropertyName); string propertyNamePrefix = (showReferencesInline ? referencePropertyName + "." : ""); if (showReferencesInline) { if (referencesLookup[referencePropertyName].Contains(fixer.TargetTypeKeyPropertyName) == false) { referencesLookup[referencePropertyName].Add(fixer.TargetTypeKeyPropertyName); autoAppendedPropertyNames.Add(propertyNamePrefix + fixer.TargetTypeKeyPropertyName); } referencedIdAttrubuteNames.Add(propertyNamePrefix + fixer.TargetTypeKeyPropertyName); } XName referenceElementName = elementNamespace + referencePropertyName; IEnumerable <XElement> referencesXml = fixer.GetReferencedXElements(coreDataItems, referencesLookup[referencePropertyName], referenceElementName, propertyNamePrefix); referencedResults.AddRange(referencesXml); } if (showReferencesInline) { Dictionary <string, IEnumerable <XElement> > referencedElementsLookup = new Dictionary <string, IEnumerable <XElement> >(); Dictionary <string, Func <string, XAttribute> > referencedElementLocatorLookup = new Dictionary <string, Func <string, XAttribute> >(); foreach (string referencePropertyName in referencesLookup.Keys) { XName referenceElementName = elementNamespace + referencePropertyName; IEnumerable <XElement> referenceElements = referencedResults.Where(f => f.Name == referenceElementName); referencedElementsLookup.Add(referencePropertyName, referenceElements); string idPropertyName = referencedIdAttrubuteNames.First(g => g.StartsWith(referencePropertyName + ".")); IEnumerable <XElement> referencedElements = referencedElementsLookup[referencePropertyName]; Func <string, XAttribute> locateByKeyFunc = f => referencedElements.Attributes(idPropertyName).FirstOrDefault(g => g.Value == f); referencedElementLocatorLookup.Add(referencePropertyName, locateByKeyFunc); } foreach (XElement coreElement in result.Where(f => f.Name == coreElementName)) { foreach (string referencePropertyName in referencesLookup.Keys) { XAttribute referenceAttribute = coreElement.Attribute(referencePropertyName); if (referenceAttribute == null) { continue; // Handles non-references } string keyValue = referenceAttribute.Value; Func <string, XAttribute> fetcher = referencedElementLocatorLookup[referencePropertyName]; XAttribute matchingKeyAttribute = fetcher(keyValue); if (matchingKeyAttribute != null) { XElement referenced = matchingKeyAttribute.Parent; coreElement.Add(referenced.Attributes()); } } coreElement.Attributes().Where(f => autoAppendedPropertyNames.Contains(f.Name.LocalName)).Remove(); yield return(coreElement); } } else { foreach (XElement anyElement in result) { yield return(anyElement); } foreach (XElement anyElement in referencedResults) { yield return(anyElement); } } if (showPagingInfo) { int totalItemCount = DataFacade.GetData <T>(filter).Count(); // TODO: there shoudn't be a query int firstShownElementNumber = ((coreElementPageNumber - 1) * coreElementItemsPerPage) + 1; int lastShownElementNumber = Math.Min(totalItemCount, firstShownElementNumber + (coreElementItemsPerPage - 1)); int shownItemsCount = Math.Max(0, (lastShownElementNumber - firstShownElementNumber) + 1); int totelPageCount = (int)Math.Ceiling((((double)totalItemCount) / ((double)coreElementItemsPerPage))); XElement pagingInfo = new XElement(elementNamespace + "PagingInfo", new XAttribute("CurrentPageNumber", coreElementPageNumber), new XAttribute("TotalPageCount", totelPageCount), new XAttribute("TotalItemCount", totalItemCount), new XAttribute("ShownItemsCount", shownItemsCount), new XAttribute("MaximumItemsPerPage", coreElementItemsPerPage) ); if (shownItemsCount > 0) { pagingInfo.Add( new XAttribute("CurrentItemNumberStart", firstShownElementNumber), new XAttribute("CurrentItemNumberEnd", lastShownElementNumber) ); } yield return(pagingInfo); } }