class Program
{
static void Main(string[] args)
{
try
{
if (args.Length == 0)
Import(DateTime.Now);
else if (args.Length == 1)
{
DateTime dateToImport;
bool isValidDate = DateTime.TryParse(args[0], out dateToImport);
if (isValidDate)
{
Import(dateToImport);
}
else
WriteToLogFile(String.Format("The Import date specified was invalid. - {0}", args[0]));
}
else if (args.Length == 2)
{
DateTime startDate;
DateTime endDate;
bool isStartDateValid = DateTime.TryParse(args[0], out startDate);
bool isEndDateValid = DateTime.TryParse(args[1], out endDate);
if (isStartDateValid && isEndDateValid && (startDate < endDate))
Import(startDate, endDate);
else
WriteToLogFile(String.Format("Invalid Date Range Specified. - Start Date Entered = {0}, End Date Entered = {1}", args[0], args[1]));
}
}
catch (Exception ex)
{
WriteToLogFile("Error in Import Process = " + ex.StackTrace);
}
}
private static void Import(DateTime dateToImport)
{
DataLayer dl = new DataLayer();
DataTable dt = dl.GetDataForImport(dateToImport);
SendToWebService(dt);
}
private static void Import(DateTime startDate, DateTime endDate)
{
DataLayer dl = new DataLayer();
DataTable dt = dl.GetDataForImport(startDate, endDate);
SendToWebService(dt);
}
private static void SendToWebService(DataTable dt)
{
if (dt == null || dt.Rows.Count == 0)
{
WriteToLogFile("Nothing to import");
return;
}
ImportService.ImportService importService = new ImportService.ImportService();
System.Collections.Generic.List<ImportService.Record> myRecords = new List<ImportService.Record>();
foreach (DataRow dr in dt.Rows)
myRecords.Add(DataRowToObject(dr));
importService.ImportData(myRecords.ToArray());
}
private static ImportService.Record DataRowToObject(DataRow myRow)
{
ImportService.Record myRecord = new ImportService.Record();
myRecord.Status = myRow.ItemArray[1].ToString();
myRecord.FirstName = myRow.ItemArray[3].ToString();
myRecord.LastName = myRow.ItemArray[4].ToString();
myRecord.DateLastStatus = Convert.ToDateTime(myRow.ItemArray[13].ToString());
return myRecord;
}
/// <summary>
/// Write messages to a log file for efficient tracking of the windows service
/// </summary>
/// <param name="strMessage"></param>
public static void WriteToLogFile(string message)
{
System.IO.StreamWriter sWriter;
string ExecutablePath = System.AppDomain.CurrentDomain.BaseDirectory;
try
{
sWriter = new System.IO.StreamWriter(ExecutablePath + "\\logs\\" + "ImportTask_" + DateTime.Now.Month + "_" + DateTime.Now.Day + "_" + DateTime.Now.Year + ".log", true);
sWriter.WriteLine("Time :" + DateTime.Now.ToShortTimeString() + " -:- " + message);
sWriter.Flush();
sWriter.Close();
}
catch (Exception ex)
{
// If the directory does not exist, then create the logs directory in the directory where
// the executable resides.
string strExceptionMessage = ex.Message;
DirectoryInfo oDir = new DirectoryInfo(ExecutablePath);
try
{
oDir.CreateSubdirectory("logs");
sWriter = new System.IO.StreamWriter(ExecutablePath + "\\logs\\" + "ImportTask_" + DateTime.Now.Month + "_" + DateTime.Now.Day + "_" + DateTime.Now.Year + ".log", true);
sWriter.WriteLine("Time :" + DateTime.Now.ToShortTimeString() + " -:- " + message);
sWriter.Flush();
sWriter.Close();
}
catch (Exception dex)
{
}
}
}
}
Refactorings
No refactoring yet !
Anonymous
August 13, 2009, August 13, 2009 18:45, permalink
The only real issue here is the fact that everything is a static method. Construct a new Program() from your Main method and do all of your work in an *instance* of Program instead.
class Program
{
public Program(string[] args)
{
// the stuff that used to be in Main goes here
}
static void Main(string[] args)
{
Program p = new Program();
}
...
}
Ants
August 13, 2009, August 13, 2009 20:32, permalink
Actually, there's still a couple other bits that should be fixed:
- Use of magic numbers in lines 75-78 to pick out columns. Use enums or actual column names instead?
- Why not just use myRow[x] instead of myRow.ItemArray[x] in lines 75-78?
- If the column data is already the correct types, why not cast directly to the type instead of calling .ToString()? In particular line 78, why not just cast to DateTime() if it contains a DateTime?
- Note the duplication of code in lines 93-96 and 107-110. Probably should move into a function, and that function should use the using() clause so that there is no need for the explicit Stream.Close().
- Computing the file path for log file in lines 93 and 107 should move into a function, and that function could probably stand to use Path.Combine().
Possible bug:
- On line 90, if you're app is installed under "Program Files", it is very likely that you don't have permissions to create directories and files unless you run elevated. Use Application.LocalUserAppDataPath instead, perhaps?
Consider:
- Use the Trace and the FileLogTraceListener classes perhaps to replace the explicit writes to log file? That way you can also add/create a TraceListener that outputs to the console if you wish.
@Anonymous: I recommend moving all that used to go into Main() into an instance Run(string [] args) method. I subscribe to the idea that constructors do minimal work to get setup, and that actual work be done in methods.
Hi all i would like someone to show me how to refactor so that it is more maintainable.
Thanks