I have a collection in MongoDb which contains objects which are derived from a class "FeedItemBase". When i query this collection, i return a list of FeedItemBase objects.
//This is my collection property in the RepoBase abstract
public IMongoCollection<T> Collection { get; set; }
//This is what my repo looks like, therefore my Collection is T = UserFeed
public class UserFeedsRepo : RepoBase<UserFeed>, IAsyncRepo<UserFeed>
{...The method below lives in this repo...}
public async Task<IEnumerable<FeedItemBase>> GetFeedItems(string userId, int skip, int limit)
{
try
{
var results = await Collection
.Aggregate()
.Match(x => x.User.Id == userId)
.Unwind<UserFeed, UnwindedFeedItems>(x => x.Items)
.SortByDescending(x => x.Items.DatePosted)
.Skip(skip)
.Limit(limit)
.ToListAsync()
.ConfigureAwait(false);
return results.Select(x => x.Items);
}
catch (Exception ex)
{
throw new Exception("An exception occured in GetFeedItems", ex);
}
}
Which is fine. If i pass these objects in this form (DTO) to my client from WebApi as Json, they are correctly serialized into their derived forms at client using $type.
However, there is a point where I need to inject these DTos into some ViewModels in order to pass down information that is not saved in my database, in their simplest forms:
FeedItemImage derives from FeedItemBase
FeedItemComment derives from FeedItemBase
The only different between the 2 objects is "ImageUrl" and "Comment" respectively.
I am having trouble converting the collection of FeedItemBase objects to their concrete forms and I can't seem to think of a clean way around it. I need them i their concrete forms so that when injected into the ViewModel constructors I can access the Comment and ImageUrl properties.
private async Task<List<FeedItemViewModelBase>> GetFeedItemViewModels(IEnumerable<Models.DTO.Feed.FeedItemBase> feedItems)
{
try
{
List<FeedItemViewModelBase> viewModels = new List<FeedItemViewModelBase>();
//This is where it is currently bombing out
var commentItems = (IEnumerable<Models.DTO.Feed.FeedItemComment>)feedItems.Where(x => x.ObjectType == "FeedItemComment");
var imageItems = (IEnumerable<Models.DTO.Feed.FeedItemImage>)feedItems.Where(x => x.ObjectType == "FeedItemImage");
//These 2 lines return populate view models to be added to the list to be returned
var commentViewModelsTask = GetFeedItemCommentViewModels(commentItems).ConfigureAwait(false);
var imageViewModelsTask = GetFeedItemImageViewModels(imageItems).ConfigureAwait(false);
viewModels.AddRange(await commentViewModelsTask);
viewModels.AddRange(await imageViewModelsTask);
return viewModels;
}
catch (Exception ex)
{
throw new Exception("There was a problem retrieving feed item viewmodels", ex);
}
}
Can someone help me with this? Or tell me if there is a better way of going about it.
Thanks in advance
The solution as Quantic pointed out was to cast each item in the list rather than trying to cast the entire collection:
var commentItems = feedItems
.Where(x => x.ObjectType == "FeedItemComment")
.Select(x => (Models.DTO.Feed.FeedItemComment)x);
Thanks Quantic