加入两个不同类型的列表并按日期排序

时间:2012-11-13 08:15:03

标签: c# list

我有第一个这样的实体列表:

public partial class Networking :EntityBase
{

    public virtual int NetWorkingId
    {
        get;
        set;
    }

    public virtual string NetWorkingParam
    {
        get;
        set;
    }

    public virtual System.DateTime NetWorkingDate
    {
        get;
        set;
    }
}

我有第二个这样的实体列表:

public partial class PrivateNetwork :EntityBase
{
    public virtual int PrivateNetworkId
    {
        get;
        set;
    }

    public virtual int ContaId
    {
        get { return _contaId; }
        set
        {
            if (_contaId != value)
            {
                if (Contact != null && Contact.ContaId != value)
                {
                    Contact = null;
                }
                _contaId = value;
            }
        }
    }

    public virtual Nullable<System.DateTime> DateCreation
    {
        get;
        set;
    }
}

我想在一个中收集这两个列表,并按日期对所有元素进行排序。

这可能吗?

6 个答案:

答案 0 :(得分:5)

使用多态可以很容易地解决这个问题;为这两个类使用公共基类或接口,它具有您要排序的DateTime属性。

示例:

public abstract class NetworkingBase : EntityBase
{
    public DateTime DateToSortOn { get; set; }
}

public interface INetworking
{
    public DateTime DateToSortOn { get; set; }
}

然后让您的课程来自NetworkingBase或实施INetworking

public partial class Networking : NetworkingBase
{
    ...
}

public partial class PrivateNetwork : NetworkingBase
{
    ...
}

public partial class Networking : EntityBase, INetworking
{
    ...
}

public partial class PrivateNetwork : EntityBase, INetworking
{
    ...
}

在生成的集合上执行LINQ UnionConcat,然后执行OrderBy

答案 1 :(得分:5)

你可以做到这一点,虽然它不是很漂亮,你最终得到IEnumerable<object>所以你必须检查每个项目的类型才能使用它:

IEnumerable<object> sorted = myNetworkingList
    .Concat<object>(myPrivateNetworkList)
    .OrderBy(n => n is Networking
                 ? (DateTime?)((Networking)n).NetWorkingDate
                 : ((PrivateNetwork)n).DateCreation);

foreach (object either in sorted)
{
    if (either is Networking)
        // Networking; do something
    else
        // PrivateNetwork; do something else
}

答案 2 :(得分:2)

我之前应该问的是。 。 。

排序后你想做什么?

这个问题的答案可能会对潜在的解决方案产生重大影响。

如果答案类似于,我需要显示日期列表,您只需要按顺序排列日期。如果是这样,那么你不需要合并两个列表,你可以得到一个只是有序日期的序列并使用它。例如。

var orderedDates = networks.Select(n => n.NetworkingDate)
                   .Union(privateNetworks.Select(n => n.DateCreation))
                   .OrderBy(date => date);

如果答案是我需要显示一个链接列表,显示链接到对象ID的日期,以及识别对象类型的东西,那么你可以侥幸逃脱非常喜欢上面的,有一个匿名对象。

var orderedDates = networks.Select(n => new {Date = n.NetworkingDate, Id = n.NetWorkingId, NetworkType = n.GetType().Name})
                   .Union(privateNetworks.Select(n => new {Date = n.DateCreation, Id = n.PrivateNetWorkingId, NetworkType = n.GetType().Name}))
                   .OrderBy(n => n.Date);

但是如果答案是我需要向10个最古老的网络发送Shutdown()命令然后你真的需要一个多态解决方案,你有一个您可以调用Shutdown()方法的类型,该方法将解析为您正在使用的类型的特定Shutdown()方法。

仅在用户khellang's answer不适合您时使用的多态解决方案

来自对另一个答案的评论

  

@BinaryWorrier我选择了这个答案,因为我已经有了记录   数据库,所以如果我选择添加一个新的界面我将如何处理   在添加界面之前已经存储了记录吗?

我发现很难相信你的ORM不会允许你向实体类添加接口而不是 - 不知何故 - 标记该接口和/或它的成员,以便它们被ORM忽略。

但是,假设您无法添加新接口或基类,您仍然可以多态地执行此操作。

添加接口,添加一个实现每个网络类(Abstractor类)的接口的类,然后将网络类转换为Abstractor类,将它们添加到{{1并排序该列表。

List<INetwork>

答案 3 :(得分:1)

创建一个在两个类中都有日期和实现的接口。之后排序很容易。

public interface INetwork
{
    DateTime? Date { get; }
}

public partial class Networking :EntityBase, INetwork
{
    public DateTime? Date
    {
        get { return NetWorkingDate; }
    }
}

public partial class PrivateNetwork :EntityBase, INetwork
{
    public DateTime? Date
    {
        get { return DateCreation; }
    }
}

var commonList = new List<INetwork>();
// Add instances of PrivateNetwork and Networking to the list

var orderedByDate = commonList.OrderBy(n => n.Date);

答案 4 :(得分:0)

第一种解决方案是使用匿名类型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Example1
{
    class Program
    {
        class Human
        {
            public string Name { get; set; }
            public string Hobby { get; set; }
            public DateTime DateOfBirth { get; set; }
        }
        class Animal
        {
            public string Name { get; set; }
            public string FavouriteFood { get; set; }
            public DateTime DateOfBirth { get; set; }
        }

        static void Main(string[] args)
        {
            var humans = new List<Human>
            {
                new Human
                {
                    Name = "Kate",
                    Hobby = "Fitness",
                    DateOfBirth = DateTime.Now.AddYears(-27),
                },
                new Human
                {
                    Name = "John",
                    Hobby = "Cars",
                    DateOfBirth = DateTime.Now.AddYears(-32),
                },
            };

            var animals = new List<Animal>
            {
                new Animal
                {
                    Name = "Fluffy",
                    FavouriteFood = "Grain",
                    DateOfBirth = DateTime.Now.AddYears(-2),
                },
                new Animal
                {
                    Name = "Bongo",
                    FavouriteFood = "Beef",
                    DateOfBirth = DateTime.Now.AddYears(-6),
                },
            };

            var customCollection = (from human in humans
                                    select new
                                        {
                                            Name = human.Name,
                                            Date = human.DateOfBirth,
                                        }
                                        ).Union(from animal in animals
                                                select new
                                                    {
                                                        Name = animal.Name,
                                                        Date = animal.DateOfBirth,
                                                    }).OrderBy(x => x.Date);


            foreach (dynamic customItem in customCollection)
                Console.WriteLine(String.Format("Date: {0}, Name: {1}",      customItem.Date, customItem.Name));

            Console.Read();
        }
    }
}

或没有匿名类型(创建CustomClass):

...
class CustomClass
        {
            public string Name { get; set; }
            public DateTime Date { get; set; }
        }
...
var customCollection = (from human in humans
                                    select new CustomClass
                                        {
                                            Name = human.Name,
                                            Date = human.DateOfBirth,
                                        }
                                        ).Union(from animal in animals
                                                select new CustomClass
                                                    {
                                                        Name = animal.Name,
                                                        Date = animal.DateOfBirth,
                                                    }).OrderBy(x => x.Date);


            foreach (CustomClass customItem in customCollection)
                Console.WriteLine(String.Format("Date: {0}, Name: {1}", customItem.Date, customItem.Name));

...

答案 5 :(得分:0)

我只是添加了一个基类并将其指定为两个列表类的父类。然后简单地做了工会。它成功了