2012-11-13 14 views
6

によってそれらを並べ替える私はこのようなエンティティの最初のリストがあります:、異なるタイプの二つのリストを結合し、日付

public partial class Networking :EntityBase 
{ 

    public virtual int NetWorkingId 
    { 
     get; 
     set; 
    } 

    public virtual string NetWorkingParam 
    { 
     get; 
     set; 
    } 

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

をそして私はこのようなエンティティの第2のリストがあります:

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; 
    } 
} 

Iをこれらの2つのリストを1つにまとめ、すべての要素を日付順にソートしたいと考えています。

これは可能ですか?

+0

何か試しましたか? Linqさんの連合OrderByが助けてくれるかもしれません... –

+0

はい私はUnionを試しましたが、問題は同じフィールドがないので並べ替える方法です – kbaccouche

+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 UnionまたはConcat、次にOrderByを結果のコレクションに付けます。あなたがそれを使用することができます前に、あなたは、各項目の種類を確認する必要があり、それは非常にきれいではありませんが、あなたは、これを行うことができ、あなたがIEnumerable<object>で終わる

+5

これは正しくありません(共通の基盤が必要* *)。 「union」オブジェクトを作成することができます(匿名または名前付き)。共通基盤の必要はありません。 –

+0

@pstそれでは、匿名オブジェクトのリストになるでしょうか? – khellang

+0

私は彼がEntityBaseに基づいてより多くのエンティティを持っていると思います。たぶんこの日付は、これらのクラスには関係ありません。 –

5

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 
} 
+0

-1:これは、多形性で最もよく解決される問題に対する醜い、ハックな解決方法です。3番目の 'CafeWifiNetwork'タイプが追加されたときには、元のdevs(_famously faulty_)メモリ以外に何もありません - このlinq&foreachループを変更する必要があると言ってください。 @khellangで提案されているアプローチのいずれかを使用すると、コンパイラはコードを正しく記述するように強制します。それはうまくいくでしょうが、私はコードレビューを一切受け入れません。 –

+0

@Binary 2つのクラスの間に共通するものは何もありません。つまり、日付プロパティは同じ型ではなく、同じ名前でもありません。したがって、共通のインターフェイスを作成することは実際には多形性ではありません。無関係なオブジェクトの)は、結果が消費されるコード内に置くのではなく、クラス自体で離れてしまいます。ネットワーキングと関係がないときは、特に 'INetworking'というインターフェースに名前をつけません。それは 'IArbitraryObejctThatHasANullableDateTimeProperty'のようなものです。 – Rawling

+0

私は心から反対します。質問者がリストをマージして並べ替えることが必要な理由がいくつかあります。概念的にはあるレベル**で同じものです**。日付が「異種」であるという議論は偽であり、「DateTime?」は両方をカバーする。最後に、「INetworkingCreatedDate」インタフェースを単一のメンバに持つことは間違いありません。あなたが「クラスで厄介な操作を隠しているだけ」であっても、コンパイラ**によって関係が強化されるのは、コードベース全体を通してさまざまな場所に分散されているよりも良いでしょう。 –

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); 
2

私が以前に質問したはずのものは何ですか。 。 。

ソート後に何をしたいですか?

この回答は、潜在的な解決策に大きな影響を与える可能性があります。

答えがの場合は、日付の一覧が表示されるようにする必要があります。は、日付のみが必要です。そうであれば、2つのリストをマージする必要はありません。ただ順序付けられた日付のシーケンスを取得し、それを使用することができます。

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

答えは、私はオブジェクトのIDにリンク日付、およびオブジェクトの種類を識別するために何かを示すリンクのリストを表示する必要がであれば、あなたは非常に何かを離れて得ることができます上記のように、Anonymousオブジェクトを使用します。

しかし
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()メソッドに解決されます。ユーザーkhellang's answerは、私はすでに のレコードを持っているので、私はこの答えを選んだ@BinaryWorrier別の答え

上のコメントから、あなた

のために動作しない場合にのみ使用する

ポリモーフィックソリューション新しいインターフェイスを追加する場合は、 を、すでにインターフェイスを追加する前に保存したレコードとどのように扱うのですか?

ORMでエンティティクラスにインターフェイスを追加することはできません。何らかの形でそのインターフェイスやORMのメンバーには表示されないため、ORMによって無視されます。

ただし、新しいインターフェイスまたはベースクラスを追加できないと仮定しても、これを多態的に行うことができます。

List<INetwork>にそれらを追加し、そのリストを並べ替え、インタフェースを追加するには、ネットワーククラス(Abstractorクラス)ごとに、その後、Abstractorクラスにネットワーククラスを変換するインタフェースを実装するクラスを追加します。

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

public class PrivateNetworkAbstractor 
    :INetwork 
{ 
    private PrivateNetwork network; 
    public PrivateNetworkAbstractor(PrivateNetwork network) 
    { 
     this.network = network; 
    } 
    public DateTime? Date 
    { 
     get { return network.DateCreation; } 
    } 
} 

public class NetworkingAbstractor 
    : INetwork 
{ 
    private Networking networking; 
    public NetworkingAbstractor(Networking networking) 
    { 
     this.networking = networking; 
    } 
    public DateTime? Date 
    { 
     get { return networking.NetWorkingDate; } 
    } 
} 
... 

public IEnumerable<INetwork> MergenSort(IEnumerable<Networking> generalNetWorks, IEnumerable<PrivateNetwork> privateNetWorks) 
{ 
    return generalNetWorks.Select(n => new NetworkingAbstractor(n)).Cast<INetwork>() 
    .Union(privateNetWorks.Select(n => new PrivateNetworkAbstractor(n)).Cast<INetwork>()) 
    .OrderBy(n=> n.Date); 
} 
+0

+1ほぼデコレータパターン: – khellang

+0

@クリスチャンヘラング:パターンブックを後ろ向きに知っていた時がありましたが、何年も前にそれを開いていませんでしたが、今はテクニックを覚えていますが、私はその技法をパターンとして学んだことを忘れてしまった。私の脳が20年前と同じように働くことを願っています。 。 。 –

0

第1の解決策は匿名型を使用している

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)); 

... 
0

Iは、単に基本クラスを追加し、両方の親として割り当てリストのクラス。それから簡単に組合をしました。それはトリックを作った

関連する問題