Searching a Better Solution with Delegates
Hey All, I am a newbie in C# and curious about the better solution of my case.
I have a method which gets the DataTable as a parameter and creates a List with MyClass's variables and returns it.
public static List<Campaigns> GetCampaignsList(DataTable DataTable)
{
List<Campaigns> ListCampaigns = new List<Campaigns>();
foreach (DataRow row in DataTable.Rows)
{
Campaigns Campaign = new Campaigns();
Campaign.CampaignID = Convert.ToInt32(row["CampaignID"]);
Campaign.CustomerID = Convert.ToInt32(row["CustomerID"]);
Campaign.ClientID = Convert.ToInt32(row["ClientID"]);
Campaign.Title = row["Title"].ToString();
Campaign.Subject = row["Subject"].ToString();
Campaign.FromName = row["FromName"].ToString();
Campaign.FromEmail = row["FromEmail"].ToString();
Campaign.ReplyEmail = row["ReplyEmail"].ToString();
Campaign.AddDate = Convert.ToDateTime(row["AddDate"]);
Campaign.UniqueRecipients = Convert.ToInt32(row["UniqueRecipients"]);
Campaign.ClientReportVisible = Convert.ToBoolean(row["ClientReportVisible"]);
Campaign.Status = Convert.ToInt16(row["Status"]);
ListCampaigns.Add(Campaign);
}
return ListCampaigns;
}
And one of my another DataTable method gets the DataTable from the database with given parameters. Here is the method.
public static DataTable GetNewCampaigns()
{
DataTable dtCa开发者_高级运维mpaigns = new DataTable();
Campaigns Campaigns = new Campaigns();
dtCampaigns = Campaigns.SelectStatus(0);
return dtCampaigns;
}
But the problem is that, this GetNewCampaigns method doesnt take parameters but other methods can take parameters. For example when I try to select a campaign with a CampaignID, I have to send CampaignID as parameter. These all Database methods do take return type as DataTable but different number of parameters.
public static DataTable GetCampaignDetails(int CampaignID)
{
DataTable dtCampaigns = new DataTable();
Campaigns Campaigns = new Campaigns();
dtCampaigns = Campaigns.Select(CampaignID);
return dtCampaigns;
}
At the end, I want to pass a Delegate to my first GetCampaignList Method as parameter which will decide which Database method to invoke. I dont want to pass DataTable as parameter as it is newbie programming.
Could you pls help me learn some more advance features. I searched over it and got to Func<> delegate but could not come up with a solution.
It looks like you have two duplicate methods, with the only difference being a specific operation on an object (in this case a method call on Campaigns that returns a DataTable). You're trying (I think) to refactor this into one method, with that one operation abstracted. This is a perfect job for a lambda expression.
public static DataTable GetCampaignInSomeWay(Func<Campaigns, DataTable> CampaingsDelegate)
{
DataTable dtCampaigns = new DataTable();
Campaigns Campaigns = new Campaigns();
dtCampaigns = CampaingsDelegate(Campaigns);
return dtCampaigns;
}
And then call it thusly:
GetCampaignInSomeWay(C => C.Select(someCampaignId));
or
GetCampaignInSomeWay(C => C.SelectStatus(0));
The family of Action and Func delegates are extremely useful for things like this. Here are some of the docs. Note that both Action and Func have multiple generic overloads
http://msdn.microsoft.com/en-us/library/bb549151.aspx
http://msdn.microsoft.com/en-us/library/018hxwa8.aspx
I am not a huge fan of DataTable
as such, but I would not say that passing one into another method is newbie programming. On the contrary, it helps the code follow the Single Responsibility Principle. Take the following:
List<Campaigns> list = GetCampaignsList(GetNewCampaigns());
Here it is very clear what the methods do: GetNewCampaigns
gets new campaigns, and GetCampaignsList
takes a DataTable
and returns the contents as a list instead. Each method has one clear reponsibility. If you would pass a delegate to GetCampaignsList
it would suddenly do two things; invoke the delgate to get results, and convert the format of the result to a list.
There are some changes that I would suggest in your design though:
- Change names of the type
Campaigns
toCampaign
since I imagine that each instance represents a single campaign. - Change the return type of
GetCampaignsList
return anIEnumerable<Campaign>
instead, and probably change the method name intoGetCampaigns
instead.
精彩评论