What I wanted to do with the implementation was to create a
base for all the checks and validation and any child class to provide their own
implementation of the algorithm. I decided to leave the IDisposable since later
own new check or a base implementation could be added.
|
/// <summary> /// RepositorySynch will contain basic functionality for
validation and property holding. /// </summary> public abstract class RepositorySynch : IDisposable { //
Properties public
string SourcePath { get;
private set;
} public
string DestinationPath { get; private set; } public
DirectoryInfo SourceDirectory { get; private set; } public
DirectoryInfo DestinationDirectory { get; private set; } public
RepositorySynch(string SourcePath, string DestinationPath) { this.SourcePath
= SourcePath; this.DestinationPath
= DestinationPath; } /// <summary> /// Validate both source and destination path and create a
new instance of the directory info. /// </summary> protected
void ValidatePaths() { if
(Directory.Exists(SourcePath)) SourceDirectory = new DirectoryInfo(SourcePath); else throw
new DirectoryNotFoundException(string.Format("Unabled
to find source: {0}.", SourcePath)); if
(Directory.Exists(DestinationPath)) DestinationDirectory = new DirectoryInfo(DestinationPath); else throw
new DirectoryNotFoundException(string.Format("Unabled
to find destination: {0}.", DestinationPath)); } public
virtual void
Synch() { ValidatePaths(); } public
void Dispose() { } } |
The second code listing illustrates an implementation
with a specific logic set and naming convention rules. The idea below was to
leverage linq as much as possible to assist in filtering the data and getting
down to the files the needed to be copied.
|
/// <summary> /// InvoiceRepositorySynch will keep two different invoices
repositories in synch. /// </summary> public class InvoiceRepositorySynch
: RepositorySynch { /// <summary> /// Specific to this implementation and how the folders are
named. /// </summary> private
struct ProcessStruct { public
int Year; public
int Month; } public
InvoiceRepositorySynch(string SourcePath, string DestinationPath) : base(SourcePath,
DestinationPath) { } /// <summary> /// Override Synch, still calling the base so we don't have
to recall the validation function. /// </summary> public
override void
Synch() { base.Synch(); //
Gather Stats - Folder are named as year ex. 2010 and the subfolders are named
ex. 12-2010 // We
only want current month and next month. int
currentYear = DateTime.Now.Year; int
currentMonth = DateTime.Now.Month; int
futureMonth = currentMonth + 1; // Run
Current Process(currentYear,
currentMonth); //
Calculate Next if
(currentMonth == 12) { futureMonth = 1; currentYear += 1; } // Run
Future Process(currentYear,
futureMonth); } /// <summary> /// Synch the folders /// </summary> /// <param
name="year"></param> /// <param
name="month"></param> private
void Process(int
year, int month) { try { ProcessStruct
pStruct = new ProcessStruct()
{ Month = month, Year = year }; //
Get the year directory DirectoryInfo
sourceDir = SourceDirectory.GetDirectories().Where(d
=> d.Name == pStruct.Year.ToString()).FirstOrDefault(); DirectoryInfo
destinationDir =
DestinationDirectory.GetDirectories().Where(d => d.Name ==
pStruct.Year.ToString()).FirstOrDefault(); if
(sourceDir != null && destinationDir
!= null) { //
Get the month directory DirectoryInfo
sourceMonth =
sourceDir.GetDirectories().Where(d => d.Name ==
ValidName(pStruct)).FirstOrDefault(); DirectoryInfo
destinationMonth =
destinationDir.GetDirectories().Where(d => d.Name ==
ValidName(pStruct)).FirstOrDefault(); if
(sourceMonth != null &&
destinationMonth != null) { // Get the arrays for file info in both directories FileInfo[] sourceFiles = sourceMonth.GetFiles(); FileInfo[] destinationFiles =
destinationMonth.GetFiles(); // In this case we only want to perform our last check
when the source contains more files if (sourceFiles.Length >
destinationFiles.Length) { // Get the filenames array List<string>
sourceFileNames = (from f in sourceFiles
select f.Name).ToList<string>(); List<string>
destinationFileNames = (from f in destinationFiles
select f.Name).ToList<string>(); // Get all matches for removal List<string>
matches = (from s in
sourceFileNames
join d in
destinationFileNames on s equals d
select s).ToList<string>(); // Remove matches to keep a list of all the missing
filenames
sourceFileNames.RemoveAll(a => { return matches.Contains(a); }); // Copy missing files FileInfo[] filesToCopy = (from f in
sourceFiles
join c in
sourceFileNames on f.Name equals c select f).ToArray<FileInfo>(); foreach (FileInfo
f in filesToCopy) {
f.CopyTo(destinationMonth.FullName + @"\\"
+ f.Name); } } } } } catch
(Exception ex) { throw ex; } } private
string ValidName(ProcessStruct
pStruct) { return
string.Format("{0}-{1}",
pStruct.Month < 10 ? "0" +
pStruct.Month.ToString() : pStruct.Month.ToString(),
pStruct.Year.ToString()); } } |
Another way could be to order by the last updated date on
the files and only check the files that have change within a certain
period of time. I hope this have been helpful and I know that this is just one
of many ways to complete this task so please leave comments or suggestions.
Thank you in advance.

Join the conversation! Your thoughts help the community grow.