The structure of the repeating property pattern
I have a class DownloadManager
that manages multiple objects DownloadItem
. Everyone DownloadItem
has events like ProgressChanged
and DownloadCompleted
. Typically you want to use the same event handler for all loaded items, so it's a little annoying to have to set event handlers multiple times for each DownloadItem
.
Thus, I need to decide which pattern to use:
-
Use one
DownloadItem
as a template and clone it if neededvar dm = DownloadManager(); var di = DownloadItem(); di.ProgressChanged += new DownloadProgressChangedEventHandler(di_ProgressChanged); di.DownloadCompleted += new DownloadProgressChangedEventHandler(di_DownloadCompleted); DownloadItem newDi; newDi = di.Clone(); newDi.Uri = "http://google.com"; dm.Enqueue(newDi); newDi = di.Clone(); newDi.Uri = "http://yahoo.com"; dm.Enqueue(newDi);
-
Set event handlers to
DownloadManager
and copy events to eachDownloadItem
one that is enqueued.var dm = DownloadManager(); dm.ProgressChanged += new DownloadProgressChangedEventHandler(di_ProgressChanged); dm.DownloadCompleted += new DownloadProgressChangedEventHandler(di_DownloadCompleted); dm.Enqueue(new DownloadItem("http://google.com")); dm.Enqueue(new DownloadItem("http://yahoo.com"));
-
Or use some kind of factory
var dm = DownloadManager(); var dif = DownloadItemFactory(); dif.ProgressChanged += new DownloadProgressChangedEventHandler(di_ProgressChanged); dif.DownloadCompleted += new DownloadProgressChangedEventHandler(di_DownloadCompleted); dm.Enqueue(dif.Create("http://google.com")); dm.Enqueue(dif.Create("http://yahoo.com"));
What would you recommend?
a source to share
Why are DownloadItems responsible for reporting (in terms of API design)?
I would say the DownloadManager is responsible for downloading the DownloadItems and therefore also for reporting. (Of course, the internal implementation strategy may differ.)
I would go with the second option:
var dm = DownloadManager
{
"http://google.com",
new DownloadItem("http://yahoo.com") { Retries = 5 }
};
dm.ProgressChanged += (sender, e) =>
Console.WriteLine("Download {0}: {1:P}", e.Uri, (double)e.Progress / 100.0);
dm.DownloadCompleted += (sender, e) =>
Console.WriteLine("Download {0}: completed!", e.Uri);
dm.DownloadAllCompleted += (sender, e) =>
Console.WriteLine("All downloads completed!");
dm.Add("http://stackoverflow.com");
dm.DownloadAllAsync();
If you have a copy of the Framework Design Guide (2nd ed.) On hand, see pages 305-33 (Event-Based Asynchronous Pattern).
a source to share