0

ライブラリ関数を作成しましたが、追加のパラメーターを使用して非常によく似た処理を行うオーバーロードを追加したいと思います。既存のコードは次のようになります。

public class MealsAllocation
{
    public int mealId;
    public List<CrewSummary> crew;

    private MealsAllocation() { }
    public MealsAllocation(int MealId) {
        mealId = MealId;
        string connStr = ConfigurationManager.ConnectionStrings["LocalSqlServer"].ConnectionString;
        SqlConnection conn = new SqlConnection(connStr);

        //first fill an ienumerable redemption object for the meal
        List<MealRedemption> mealRedemptions = new List<MealRedemption>();
        SqlCommand cmdRed = new SqlCommand("tegsGetMealsRedemption", conn);
        cmdRed.CommandType = CommandType.StoredProcedure;
        cmdRed.Parameters.Add(new SqlParameter("@mealId", MealId));
        conn.Open();
        SqlDataReader drRed = cmdRed.ExecuteReader();
        while (drRed.Read())
        {
            MealRedemption mr = new MealRedemption(Convert.ToInt32(drRed["crewId"]), Convert.ToDateTime(drRed["creation"]), Convert.ToInt32(drRed["redeemed"]));
            mealRedemptions.Add(mr);
        }
        conn.Close();

        //then fill the crew list
        crew = new List<CrewSummary>();
        SqlCommand cmdCrew = new SqlCommand("tegsGetMealsAllocation", conn);
        cmdCrew.CommandType = CommandType.StoredProcedure;
        cmdCrew.Parameters.Add(new SqlParameter("@mealId", MealId));
        conn.Open();
        SqlDataReader drCrew = cmdCrew.ExecuteReader();
        while (drCrew.Read())
        {
            int drCid = Convert.ToInt32(drCrew["id"]);
            List<MealRedemption> drMr = mealRedemptions.FindAll(red => red.crewId == drCid) ;
            CrewSummary cs = new CrewSummary(drCid, Convert.ToInt32(drCrew["allocation"]), drMr );
            crew.Add(cs);
        }
        conn.Close();

    }

そこで、次のような新しいオーバーロードを追加したいと思います。

    public MealsAllocation(int MealId, int crewId)
    {
    }

基本的に、これはほとんど同じですが、上記とは少し異なります。

「コピーアンドペーストの継承」を回避するための良い戦略は何でしょうか?つまり、上記をリファクタリングして、過負荷になりやすいようにするための良い方法はありますか?

4

5 に答える 5

1

コンストラクター内でこれらすべてを実行することはお勧めしませんが、オプションのパラメーターを最後に追加するだけで済みます。

public class MealsAllocation  
{  
    public int MealId { get; set; }
    public int CrewId { get; set; }

    public List<CrewSummary> Crew { get; set; };

    public MealsAllocation(int mealId, int crewId = 0)  
    {  
        this.MealId = mealId;
        this.CrewId = crewId;

        if(this.CrewId = 0) // etc...
} 

補足:オブジェクトの周りにステートメントを追加する必要があります。そうしusingないと、接続やメモリリークが発生する可能性があります。個人的には、データアクセス層を作成し、そこにすべてのデータ関連のメソッドを配置して、ビジネス層全体で再利用できるようにします。SqlConnectionSqlCommandSqlDataReader

Lazy<T>また、これはオブジェクトの適切な候補になると思います:http: //msdn.microsoft.com/en-us/library/dd642331.aspx

于 2012-08-20T13:14:39.387 に答える
1

internalロジックを関数に移動して、このアセンブリでのみアクセスできるようにし、このクラスに移動してオプションのパラメーターを使用するのはどうですか...次のようになります。

public class MealsAllocation
{
    public int mealId;
    public List<CrewSummary> crew;

    private MealsAllocation() 
    {
    }

    public MealsAllocation(int MealId) 
    {
        DoWork(MealId);
    }

    public MealsAllocation(int MealId, int crewId)
    {
        DoWork(MealId, crewId);
    }

    internal void DoWork(int MealId, int crewId = -1)
    {
        // have your logic here based on your parameter list

        // valid crewId passed, then add new param for DB proc
        if (crewId > -1)
        {
            cmdCrew.Parameters.Add(new SqlParameter("@crewId", crewId));
        }
    }
}
于 2012-08-20T13:06:47.233 に答える
1

オブジェクト初期化子を使用できます

var mealRedemption = new
{ 
  MealId = yourvlue,
  Crew = crew
};

リンク: http: //msdn.microsoft.com/en-us/library/bb384062.aspx

于 2012-08-20T13:06:48.617 に答える
1

最初に頭に浮かぶのは、コードの大きなチャンクを2つの異なるメソッドに分割して、各メソッドに特殊な機能を与えることです。

public MealsAllocation(int MealId) 
{
    List<MealRedemption> mealRedemptions = LoadMealRedemptions(MealID);
    LoadCrewSummaryByMeal(mealRedemptions, MealID);
}

他のコンストラクターは

public MealsAllocation(int MealId, int crewId) 
{ 
    List<MealRedemption> mealRedemptions = LoadMealRedemptions(MealID);
    LoadCrewSummaryByCrew(mealRedemptions, MealID, crewID);
} 

最初のコンストラクターでは、MealRedemptionsリストをロードするプライベートメソッドを呼び出し、その出力を取得して、MealIDと最初のメソッドから取得したリストのみを使用してCrewSummaryリストをロードする特殊なメソッドに渡します。

2番目のコンストラクターでは、最初のコンストラクターで使用したのと同じメソッドを使用してから、CrewSummaryのロードに別のメソッドを使用できます。2番目のコンストラクターの要件は明確ではなく、この2番目のメソッドの設計を変更する可能性があります(つまり、crewIDパラメーターを使用して、CrewSummaryリストを作成するための内部動作をどのように変更しますか?)

于 2012-08-20T13:07:20.113 に答える
1

コンストラクターをオーバーロードしたいので、次のようなアプローチを試すこともできます。

public MealsAllocation(int MealId) : this (MealId, null)
{
}
public MealsAllocation(int MealId, int? crewId) 
{
  // Initialize your instance as needed
  if (crewId.HasValue)
  {
    // Do some more stuff
  }
}
于 2012-08-20T13:14:11.003 に答える