2011-12-27 5 views
5

私のDBからデータを取得し、( "すべて"のオプション値を含む)移入されたSelectListオブジェクトを返す次の2つのメソッドがあります。問題は、それらが異なるリポジトリオブジェクトにアクセスし、異なるID名(StatusIdとTeamId)を持っていることを除いて、ほとんど同じです。私は、リポジトリをパラメータとして受け取り、ID名が何かであるべきか、反射や何らかのラムダ式を使って何かを調べるという、単一のメソッドにリファクタリングする機会があると思いますが、これを達成する。1つのメソッドにSelectListを生成する2つのメソッドをリファクタリングします

private SelectList GetStatusSelectList(int selectedStatusId) 
{ 
    List<MemberStatus> statusList = _memberStatusRepository.All().ToList(); 
    statusList.Insert(0, new MemberStatus {StatusId = 0, Name = "All"}); 
    var statusSelectList = new SelectList(statusList, "StatusId", "Name", selectedStatusId); 
    return statusSelectList; 
} 

private SelectList GetTeamSelectList(int selectedTeamId) 
{ 
    List<MemberTeam> teamList = _memberTeamRepository.All().ToList(); 
    teamList.Insert(0, new MemberTeam { TeamId = 0, Name = "All" }); 
    var teamSelectList = new SelectList(teamList, "TeamId", "Name", selectedTeamId); 
    return teamSelectList; 
} 

これらを1つの方法でどのようにリファクタリングするかを知る手助けは誰にもありますか?

+1

これらのクラスを編集できますか?つまり、インターフェースを追加できますか? –

+0

はい... _memberTeamRepostioryと_memberStatusRepositoryの両方がIRepositoryインターフェイスを実装しています。そのインタフェースには、IQueryable All()のようなメソッドを含むDBとやりとりするすべてのメソッドがあり、指定されたTEntityの_dbSetを単純に返します。 – bigmac

+0

MemberTeamとMemberStatusについて - 直接または部分クラスでそれらを変更できますか? – foson

答えて

2

あなたは次のことを試してください:

private SelectList GetStatusSelectList(int selectedStatusId) 
{ 
    return GetGenericSelectList<MemberStatus>(selectedStatusId, _memberStatusRepository.All().ToList(), "StatusId"); 
} 

private SelectList GetTeamSelectList(int selectedTeamId) 
{ 
    return GetGenericSelectList<MemberTeam>(selectedTeamId, _memberTeamRepository.All().ToList(), "TeamId"); 
} 

private SelectList GetGenericSelectList<T>(int selectedTeamId, List<T> list, string idFieldName) where T : new() 
{ 
    var firstItem = new T(); 
    (firstItem as dynamic).Name = "All"; 
    var l = new List<T>(list); 
    l.Insert(0, firstItem); 
    return new SelectList(l, idFieldName, "Name", selectedTeamId); 
} 

このソリューションは理想的ではありませんし、いくつかの規則に依存している(例えば、すべてのアイテムがName性質を持っている必要があります)。しかし、それは悪くない方法で始まると思われる。プロパティ名の代わりに式を使うことで、コンパイル時のチェックでプロパティ名を変更することができます。

+0

コードをありがとう。これはうまくいくようですが、私には2つの質問があります。まず、コードの3行目と4行目を削除し、代わりに単に 'list.Insert(0、firstItem)'を使用しました。これに問題はありますか?第2に、私はT:new()がメソッドシグネチャのどこにあるのかわかりません。これが何をしているのか教えていただけますか? – bigmac

+0

引数から新しいリストを作成します。それ以外の場合、既存のリストは変更されます(既存のリストを渡し、関数は新しい要素を挿入します)。それは問題ではないかもしれませんが、もしこのオリジナルのリストがこの方法の横のどこかで使われたらどうでしょうか?新しい制約に関しては、 'new T()'を実行するだけです。詳細はhttp://msdn.microsoft.com/en-us/library/sd2w2ew5.aspxを参照してください。 –

+1

これは私の直ちに必要とする最もクリーンな解決策ですので、ありがとうございますthe_joric! – bigmac

3

これは最も一般的なものですが、MemberStatusMemberTeamにはIIdentifiableが実装されている必要があります。あなたのケースに適用できるかどうかわかりません。もしそうなら、これが行く方法でしょう。

private SelectList GetList<T>(IRepository repository, int id, string name) 
    where T : IIdentifiable, new() 
{ 
    List<IIdentifiable> list = repository.All().ToList(); 
    list.Insert(0, new T() { Name = name, Id = id }); 
    var statusSelectList = new SelectList(list, "Id", "Name", id); 
} 

そして、私が見たものから、インタフェースコード

interface IIdentifiable 
{ 
    int Id { get; set; } 
    string Name { get; set; } 
} 
+0

ありがとうTomislav。ただし、MemberTeamとMemberStatusのPOCOオブジェクトは非常に単純で、どちらもNameプロパティを持っていますが、それぞれIdプロパティ(StatusIdとTeamId)の一意の名前を持っています。これらのプロパティをそのまま名前を付けたままにして、あなたが記述するインターフェイスを実装する方法はありますか?私はDBデザインをよりわかりやすい名前にしたいと思う傾向がありますが、推薦されればより一般的なIDのフィールドを使用するように説得することができます。 – bigmac

+0

もちろん、クラスの 'StatusId'と' TeanId'に 'IIdentifiable.Id'プロパティをマップするだけです。 'int Id {get {戻り値StatusId; }セット{StautsId =値; }} 'をあなたの' MemberStatus'クラスに追加します。これはうまくいかないでしょうか? –

+1

@トミスラフ...ありがとう。同様のものを投稿したFosonに言及したように、私はドメインモデルのより堅牢なリファクタリングのためにあなたのメソッドを使用するつもりですが、the_joricの答えは私が投稿した質問の中で最も簡潔です。 。しかし、もう一度、あなたに感謝して、私はこのプロジェクトを構築し続けていくうちに、私はいくつかの新しい方向を見せてくれました! – bigmac

1

、単一のメソッドにこれをリファクタリングする方法で、主なハードルは、右の決定に加えて、new MemberStatusnew MemberTeamコールです使用するリポジトリ。

エレガントなソリューションを考え出すには、さらにインフラストラクチャを設定する必要があります。基本的には、タイプに基づいて正しいリポジトリを解決する必要があり、オブジェクトインスタンスを構築するための工場が必要です。

以下は、単一のメソッドにコードをリファクタリングしますが、あなたが既に持っている別の方法よりも良く(私の意見では)ありません:

private SelectList GetSelectList<T>(int selectedId, Func<List<T>> repoAllFunc, Func<T> typeNewFunc, string idName) 
{ 
    List<T> list = repoAllFunc(); 
    list.Insert(0, typeNewFunc()); 
    var selectList = new SelectList(list, idName, "Name", selectedId); 
    return selectList; 
} 

あなたは、このようにそれを呼び出すことができます。

var memberStatusSelectList = 
    GetSelectList<MemberStatus>(
     id, 
     () => _memberStatusRepository.All().ToList(), 
     () => new MemberStatus {StatusId = 0, Name = "All"}); 
+0

Ethan、私もあなたのコードを試していますが、あなたのメソッドを呼び出す方法を理解するのに苦労しています。私はラムダ式を取ると仮定しますが、私はこれらのことを初めて知っているので、Funcのパラメータのために渡すものについてのポインタを私に与えることができますか? – bigmac

+0

@bmccleary使用方法の例を追加しました。この例の関数はパラメータを取らないので、構文はデリゲート構文の場合と同じくらい単純です。それ以外の場合は、少し醜いです。 –

+0

サンプルコードと説明をありがとうございます。私は今すぐthe_joricの答えを受け入れるつもりですが、それは私のすぐれたニーズのために少しきれいですが、私はしばらくのうちに代理人をメソッドに渡す方法を見つけようとしていて、あなたのサンプルは、私のコードの他の領域、非常にありがとう! – bigmac

0

IRepositoryに「機能」がいくつか追加されている場合は、よりクリーンなコードが表示されます。

All()の代わりに、SingleRecordsWithAllRecord()の最初の2行を処理するメソッドがあります。リポジトリに独自のDataValueFieldDataTextFieldを定義させます。

private SelectList GetSelectList(IRepository repo, int selectedId) 
{ 
    var selectListAll = repo.SingleRecordsWithAllRecord().ToList(); 

    return new SelectList(selectListAll, 
         repo.DataValueField, 
         repo.DataTextField, 
         selectedId); 
} 
+0

オースティン、私はここにあなたの思考パターンが好きです。私はコードを続けながら試してみたいと思いますが、今のところ、the_joricの答えは私の直ちに必要とするものです。入力いただきありがとうございます! – bigmac

1

あなたはクレイジー少しインタフェースを移動して、次の操作を行うことができます

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

namespace ConsoleApplication3 
{ 

    public class MemberStatus : IDefault<MemberStatus> 
    { 
     public int StatusId { get; set; } 
     public string Name { get; set; } 

     public MemberStatus Default 
     { 
      get { return new MemberStatus() { StatusId = 0, Name = "All" }; } 
     } 

     public string IdName 
     { 
      get { return "StatusId"; } 
     } 
    } 

    public class MemberTeam : IDefault<MemberTeam> 
    { 
     public int TeamId { get; set; } 
     public string Name { get; set; } 

     public MemberTeam Default 
     { 
      get { return new MemberTeam() { TeamId = 0, Name = "All" }; } 
     } 

     public string IdName 
     { 
      get { return "TeamId"; } 
     } 
    } 

    public interface IDefault<T> 
    { 
     T Default { get; } 
     string IdName { get; } 
    } 

    public interface IRepository<T> 
    { 
     IEnumerable<T> All(); 
    } 

    public class MemberStatusRepository : IRepository<MemberStatus> 
    { 
     public IEnumerable<MemberStatus> All() 
     { 
      return new[] { 
       new MemberStatus(), 
       new MemberStatus() 
      }; 
     } 
    } 
    public class MemberTeamRepository : IRepository<MemberTeam> 
    { 
     public IEnumerable<MemberTeam> All() 
     { 
      return new[] { 
       new MemberTeam(), 
       new MemberTeam() 
      }; 
     } 
    } 

    public class DataAccessLayer 
    { 
     IRepository<MemberStatus> _memberStatusRepository; 
     IRepository<MemberTeam> _memberTeamRepository; 
     public DataAccessLayer() 
     { 
      _memberStatusRepository = new MemberStatusRepository(); 
      _memberTeamRepository = new MemberTeamRepository(); 
     } 


     public SelectList<TResult> GetTeamSelectList<TRepository, TResult>(TRepository repo, int selectedTeamId) 
      where TRepository : IRepository<TResult> 
      where TResult : IDefault<TResult>, new() 
     { 
      List<TResult> teamList = repo.All().ToList(); 
      var dummyobj = new TResult(); 
      teamList.Insert(0, dummyobj.Default); 
      var teamSelectList = new SelectList<TResult>(teamList, dummyobj.IdName, "Name", selectedTeamId); 
      return teamSelectList; 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var dal = new DataAccessLayer(); 
      SelectList<MemberStatus> results = dal.GetTeamSelectList<IRepository<MemberStatus>, MemberStatus>(new MemberStatusRepository(), 5); 
      Console.WriteLine(); 
      Console.Read(); 
     } 
    } 

    public class SelectList<TResult> 
    { 
     public SelectList(List<TResult> teamList, string p, string p_2, int selectedTeamId) 
     { 

     } 
    } 

} 

あなたがインターフェイスの静的プロパティを定義することができれば、それはいいだろうが、あなたは、私はダミーのオブジェクトを作成するに頼ることはできませんので、代わりに。

+0

@foson ...うわー!すべてのコードをありがとう。私はあなたがここに向かうところを見ることができます、そして私はあなたの方法論を採用するために私のドメインクラスの少しのリファクタリングをすることに取り組むかもしれないと思うが、今のところ、the_joricの答えが私の即時のニーズに対処する最も基本的な方法だったので、それを受け入れる。しかし、もう一度、私はあなたのコードを参考にして、近い将来にいくつかのより重いリファクタリングに取り組むことができるようにしています。あなたの時間と細部に非常に感謝しています! – bigmac

+0

NP。私が言ったように、私のソリューションは少しインターフェイスが狂っている - 間違いなくより複雑/動的よりも読みにくいです。ダイナミックまたはリフレクションを使用していた場合は、個人的には、ソリューションが私の許容可能な期待値の範囲内にあることを確認するために、いくつかのパフォーマンステストを行うことになります。 – foson

関連する問題