漂亮的超载结构

时间:2012-08-20 13:00:30

标签: asp.net

我已经创建了一个库函数,并希望添加一个带有附加参数的非常类似的重载。现有代码如下所示:

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)
    {
    }

基本上这将做很多相同但与上面略有不同。

什么是避免“复制和粘贴继承”的好策略? 即一种很好的方法来重构上面的内容,以便它更容易适应过载?

5 个答案:

答案 0 :(得分:1)

如何将您的逻辑移动到internal函数,以便它只能在此程序集中访问,并且可以访问此类并使用optional parameters ...类似这样的内容:

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

答案 1 :(得分:1)

您可以使用对象初始值设定项

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

链接:http://msdn.microsoft.com/en-us/library/bb384062.aspx

答案 2 :(得分:1)

首先想到的是将两大块代码分成两种不同的方法 为每种方法提供专门的功能

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列表的专用方法。

在第二个构造函数中,您可以使用第一个构造函数中使用的相同方法,然后使用另一个方法来加载CrewSummary。你的第二个构造函数的要求不明确,可能会改变第二种方法的设计(我的意思是,你如何使用crewID参数来改变内部工作来构建CrewSummary列表?)

答案 3 :(得分: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
  }
}

答案 4 :(得分: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...
} 

附注:您需要在usingSqlConnectionSqlCommand对象周围添加SqlDataReader语句,否则可能会遇到连接和/或内存泄漏。就个人而言,我创建了一个数据访问层,并将所有与数据相关的方法放在那里,使它们可以在整个业务层中重复使用。

另外,我认为这可能是Lazy<T>对象的合适人选:http://msdn.microsoft.com/en-us/library/dd642331.aspx