/// <exception cref="NotSupportedException"><paramref name="workItemType"/> is not assignable to <see cref="IWorkItem"/>.</exception>
        protected override IEnumerable ExecuteRawQuery(Type workItemType, string queryString)
        {
            var workItems = WorkItemStore.Query(queryString);

            if (typeof(IIdentifiable).IsAssignableFrom(workItemType))
            {
                return(WorkItemMapper.Create(workItemType, workItems));
            }

            throw new NotSupportedException($"Unsupported type for performing relatives aware queries: {workItemType.Name}. To perform relatives aware queries the types involved must inherit from IIdentifiable.");
        }
        private IEnumerable GetRelatives(IEnumerable <IIdentifiable> source, RelativesExpression relativesExpression, Type itemType, DateTime asOf)
        {
            var results = Activator
                          .CreateInstance(typeof(List <>)
                                          .MakeGenericType(itemType))
                          as IList;

            var ids = source.Select(item => item.Id);

            if (!ids.Any())
            {
                return(results);
            }

            var workItemLinks = WorkItemStore.QueryLinks(GetQueryStringForRelativesOf(ids, relativesExpression.AncestorType, relativesExpression.DescendentType, relativesExpression.Direction, asOf));

            var map = new Dictionary <int, List <int> >();

            workItemLinks.Where(link => link.SourceId == 0).ToList().ForEach(link => map.Add(link.TargetId, new List <int>()));
            foreach (var ancestorId in map.Keys)
            {
                map[ancestorId].AddRange(GetTransitiveLinks(ancestorId, workItemLinks).Select(child => child.TargetId));
            }

            ids = ids.Union(workItemLinks.Select(link => link.SourceId)).Union(workItemLinks.Select(link => link.TargetId)).Where(id => id != 0);
            var workItems = HydrateAndFilterItems(ids, relativesExpression.AncestorType, relativesExpression.DescendentType, asOf);

            foreach (var ancestorId in map.Keys)
            {
                var id = ancestorId;
                // Get the ancestor from the list of hydrated work items
                var ancestorWorkItem = workItems.Single(item => item.Id == ancestorId);

                // Filter the work items to just those IDs that are in the map for this ancestor.
                // NOTE: Please note that the strategy is to start with the hydrated work items and filter to
                // those in the map, and NOT to lookup every work item in the map. The latter strategy would
                // break because the map also contains the IDs of Task Groups that have been filtered out.
                // This way we start with work items that we already know exist.
                var descendentWorkItems = workItems.Where(wi => map[id].Contains(wi.Id));

                var ancestor    = WorkItemMapper.Create(relativesExpression.AncestorType, new[] { ancestorWorkItem }).Cast <object>().Single();
                var descendents = WorkItemMapper.Create(relativesExpression.DescendentType, descendentWorkItems);

                var properTypedDescendents = GenerateListOfType(descendents, itemType);
                var result = Activator.CreateInstance(itemType, ancestor, properTypedDescendents);
                results.Add(result);
            }

            return(results);
        }
        public override void Map(
            Type targetWorkItemType,
            IEnumerable <KeyValuePair <IWorkItem, IIdentifiable> > workItemMappings,
            IWorkItemMapper workItemMapper)
        {
            var linksLookup = BuildLinksRelationships(targetWorkItemType, workItemMappings);

            // REVIEW: We don't have any cycle detection, this avoids causing stack overflows in those cases
            workItemMapper = new WorkItemMapper(workItemMapper.MapperStrategies.Except(new[] { this }));

            // If there were no items added to the lookup, don't bother querying VSO
            if (!linksLookup.Any())
            {
                return;
            }

            // Load all the items
            var workItems = Store.Query(linksLookup.SelectMany(p => p.Value).Distinct())
                            .ToDictionary(k => k.Id, e => e);

            var idToMapTargetLookup = workItemMappings.ToDictionary(k => k.Key.Id, e => e);
            var accessor            = TypeAccessor.Create(targetWorkItemType, true);


            // REVIEW: The recursion of links can cause mapping multiple times on the same values
            // For example, a common ancestor
            var previouslyMapped = new Dictionary <Tuple <int, RuntimeTypeHandle>, IIdentifiable>();

            // Enumerate through items requiring a VSO lookup and map the objects
            // There are n-passes to map, where n=number of link types
            foreach (var item in linksLookup)
            {
                var sourceWorkItem = idToMapTargetLookup[item.Key.Item1].Key;
                var targetWorkItem = idToMapTargetLookup[item.Key.Item1].Value;

#if DEBUG && TRACE
                Trace.TraceInformation("{0}: Mapping {1} on {2}", GetType().Name, item.Key.Item2, sourceWorkItem.Id);
#endif

                foreach (var property in
                         PropertiesOnWorkItemCache(
                             _inspector,
                             sourceWorkItem,
                             targetWorkItemType,
                             typeof(WorkItemLinkAttribute)))
                {
                    var def = PropertyInfoLinkTypeCache(_inspector, property);
                    if (def != null)
                    {
                        var        propertyType = def.WorkItemType;
                        var        linkType     = def.LinkName;
                        var        key          = new Tuple <int, string>(sourceWorkItem.Id, linkType);
                        List <int> linkIds;

                        if (!linksLookup.TryGetValue(key, out linkIds))
                        {
                            // Could not find any IDs for the given ID/LinkType
                            continue;
                        }


                        var wi = linkIds
                                 // Only get the new items that need to be mapped
                                 .Where(p => !previouslyMapped.ContainsKey(new Tuple <int, RuntimeTypeHandle>(p, propertyType.TypeHandle)))
                                 .Select(
                            s =>
                        {
                            IWorkItem val;
                            workItems.TryGetValue(s, out val);
                            return(val);
                        }).Where(p => p != null)
                                 .ToList();

                        var createdItems = workItemMapper.Create(propertyType, wi).ToList();

                        // Add the newly created items to the cache
                        // This allows for lazy creation of common parents
                        foreach (var createdItem in createdItems)
                        {
                            var key2 = new Tuple <int, RuntimeTypeHandle>(createdItem.Id, propertyType.TypeHandle);
                            previouslyMapped[key2] = createdItem;
                        }

                        var existing = linkIds
                                       // Only get the new items that need to be mapped
                                       .Where(
                            p =>
                            previouslyMapped.ContainsKey(
                                new Tuple <int, RuntimeTypeHandle>(p, propertyType.TypeHandle)))
                                       .Select(s => previouslyMapped[new Tuple <int, RuntimeTypeHandle>(s, propertyType.TypeHandle)]);

                        var allItems = createdItems.Union(existing).ToList();

                        // REVIEW: These steps are required as the type defined for the link may be different than targetWorkItemType
                        // ReSharper disable SuggestVarOrType_SimpleTypes
                        IList results = (IList)typeof(List <>)
                                        // ReSharper restore SuggestVarOrType_SimpleTypes
                                        .MakeGenericType(propertyType)
                                        .GetConstructor(new[] { typeof(int) })
                                        .Invoke(new object[] { allItems.Count });
                        foreach (var link in allItems)
                        {
                            results.Add(link);
                        }

                        accessor[targetWorkItem, property.Name] = results;
                    }
                }
            }
        }
        protected virtual IEnumerable ExecuteRawQuery(Type workItemType, string queryString)
        {
            var workItems = WorkItemStore.Query(queryString);

            return(WorkItemMapper.Create(workItemType, workItems));
        }
示例#5
0
 public IList Execute()
 {
     return(_mapper.Create <MockModel>(_items).ToList());
 }
示例#6
0
 public IEnumerable <MockModel> Generic()
 {
     return(_mapper.Create <MockModel>(_item).ToList());
 }