简体   繁体   中英

Returning a Sorted List of Objects based on an Abstract Class

I have an abstract class that defines basic behavior for socially used objects throughout the site (Social Collaboration Objects).

internal abstract class SCO
{
    public double HotScore { get; set; }
    public double UpVotes { get; set; }
    public double DownVotes { get; set; }
    public double VoteTotal { get; set; }
    public DateTime Created { get; set; }

    public SCO(DBItem item, List<Vote> votes )
    {
        var voteMeta = InformationForThisVote(votes, item.ID);
        UpVotes = voteMeta.UpVotes;
        DownVotes = voteMeta.DownVotes;
        VoteTotal = UpVotes - DownVotes;
        HotScore = Calculation.HotScore(Convert.ToInt32(UpVotes), Convert.ToInt32(DownVotes), Convert.ToDateTime(item["Created"]));
        Created = Convert.ToDateTime(item["Created"]);
    }

    private static VoteMeta InformationForThisVote(List<Vote> votes, int itemId)
    {
        // Loop through votes, find matches by id, 
        // and record number of upvotes and downvotes
    }
    private User GetCreatorFromItemValue(DBItem item)
    {
        // Cast User Object from property of DataBase information
    }
}

Here is a sample of inherited object:

class Post : SCO
{
    public string Summary { get; set; }
    public Uri Link { get; set; }
    public Uri ImageUrl { get; set; }

    public Post(DBItem item, List<Vote> votes)
        : base(item, votes)
    {
        Summary = (string) item["Summary"];
        Link = new UriBuilder((string) item["Link"]).Uri;
        ImageUrl = new UriBuilder((string) item["ImageUrl"]).Uri;
    }
}

Something else these classes all have in common is that the majority of the time they will be returned as a Sorted Collection. The difficulty here is you cannot embed a collection into an abstract class, because there is no way to instantiate the abstract class itself.

What I have working so far is having a Sort method as part of the abstract shown here:

    protected static List<ESCO> SortedItems(List<ESCO> escoList, ListSortType sortType)
    {
        switch (sortType)
        {
            case ListSortType.Hot:
                escoList.Sort(delegate(ESCO p1, ESCO p2) { return p2.HotScore.CompareTo(p1.HotScore); });
                return escoList;
            case ListSortType.Top:
                escoList.Sort(delegate(ESCO p1, ESCO p2) { return p2.VoteTotal.CompareTo(p1.VoteTotal); });
                return escoList;
            case ListSortType.Recent:
                escoList.Sort(delegate(ESCO p1, ESCO p2) { return p2.Created.CompareTo(p1.Created); });
                return escoList;
            default:
                throw new ArgumentOutOfRangeException("sortType");
        }
    }

Which allows me to have this in my Inherited Children classes:

    public static List<Post> Posts(SPListItemCollection items, ListSortType sortType, List<Vote> votes)
    {
        var returnlist = new List<ESCO>();
        for (int i = 0; i < items.Count; i++) { returnlist.Add(new Post(items[i], votes)); }
        return SortedItems(returnlist, sortType).Cast<Post>().ToList();
    }

This works, but it feels a little clunky. I'm still repeating a lot of code in my Sub-Classes, and I feel like that cast is an unnecessary performance deduction.

How do I best provide a way to return a sorted list of Objects based on an abstract class which are sorted in the same way, with the same properties?

It looks like there's no need for the abstract class, since there are no abstract members. Wouldn't it be best just to use a concrete base class (adding virtual members if necessary)?

Better yet, use an interface that contains all the members needed for sorting (score, votes, etc); pass collections of the interface to your sort method.

Edit Here's a simplified example:

internal interface ISCO
{
    double HotScore { get; set; }
}

class SCO : ISCO
{
    public double HotScore { get; set; }

    public static IEnumerable<T> Sort<T>(IEnumerable<T> items) where T : ISCO
    {
        var sorted = items.ToList();
        sorted.Sort();
        return sorted;
    }
}

Then you can use that single sort method for every derived class:

List<Post> PostItems = // ...
IEnumerable<Post> sorted = SCO.Sort<Post>(PostItems);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM