Repeated properties design pattern - c#

I have a DownloadManager class that manages multiple DownloadItem objects. Each DownloadItem has events like ProgressChanged and DownloadCompleted. Usually you want to use the same event handler for all download items, so it's a bit annoying to have to set the event handlers over and over again for each DownloadItem.
Thus, I need to decide which pattern to use:
Use one DownloadItem as a template and clone it as necessary
var 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 the event handlers on the DownloadManager instead and have it copy the events over to each DownloadItem that is enqeued.
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?

Why are the DownloadItems responsible for reporting progress (from an API design perspective)?
I'd say that the DownloadManager is responsible for downloading DownloadItems, and therefore also for reporting progress. (The internal implementation strategy may, of course, differ.)
I'd 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 happen to have a copy of the Framework Design Guideline (2nd ed.) at hand, have a look at pages 305--312 (Event-based Async Pattern).

I would say Template method pattern with a factory would be the right approach for this.

Related

Grammar issue with respect to anonymous functiosn

From m$ site. I don't get the += o,a what is that ???
private void GetResponse(Uri uri, Action<Response> callback)
{
WebClient wc = new WebClient();
wc.OpenReadCompleted += (o, a) =>
{
if (callback != null)
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Response));
callback(ser.ReadObject(a.Result) as Response);
}
};
wc.OpenReadAsync(uri);
}
wc.OpenReadCompleted += (o, a) => { }
This is assigning an anonymous delegate to the wc.OpenReadCompleted event. The (o,a) part are the method parameters.
o is object.
a is the EventArgs
As I can see from the signature of OpenReadCompletedEventHandler (which should be used to subscribe to OpenReadCompleted event), o is a sender and a is an instance of OpenReadCompletedEventArgs.
In general this approach of subscription to events is basically instantiating a delegate using a lambda expression, one can do this since C# 3.0.

Multiple timers with different intervals, writing to the same target

I'm writing a Windows Service that will execute different data import logic, from different data source to eventually write it to a single target, a MS CRM instance. Right now, the only thing I think will be problematic, is the writing to CRM part. The concurent reading of data from different (sometimes same) data source shouldn't really be an issue (I may be wrong on this...) So I came up with a way to make sure there are no concurent writes (create or updates) to CRM.
Here's the general design for the moment:
What happens when the service starts:
Timers = new List<System.Timers.Timer>();
CrmTransactionQueue.Lock = new object { }; //Static class. The object for locking purposes...
System.Threading.Thread.Sleep(20000); //for debugging purpose so I can attach to process before everything kicks in...
//retrieve all types that are extending BaseSyncStrategy..
var strategyTypes = Assembly.GetExecutingAssembly().GetTypes().Where(x => x.BaseType == typeof(BaseSyncStrategy));
foreach (Type strategyType in strategyTypes)
{
//create a instance of that type....
var strategy = (BaseSyncStrategy)Activator.CreateInstance(strategyType);
//create a timer for each of these, they will have different intervals...
System.Timers.Timer t = new System.Timers.Timer
{
Interval = strategy.Interval * 1000,
AutoReset = false,
Enabled = true
};
Timers.Add(t);
t.Elapsed += (sender, e) => TimerElapsed(sender, e, strategy);
t.Start();
}
What happens when the timers' interval are expired:
private void TimerElapsed(object sender, ElapsedEventArgs e, BaseSyncStrategy strategy)
{
//get timer back
var timer = (Timer)sender;
try
{
strategy.Execute();
}
catch (Exception ex)
{
Logger.WriteEntry(EventLogEntryType.Error, $"Error executing strategy {strategy.GetType().Name}: ", ex);
}
timer.Start();
}
And within all the Execute methods of objects extending BaseSyncStrategy, each time I want to update or create something in the target CRM instance, I do this:
XrmServiceContext XrmCtx = new XrmServiceContext();
//....
//code that fetches data from foreign sources and creates CRM entities...
//....
Action<XrmServiceContext> action = (XrmServiceContext ctx) =>
{
//write those created/updated objects
//ctx lets me query entities and write back to CRM...
};
CrmTransactionQueue.Execute(action, XrmCtx);
And the simple code to make sure (I think) no concurent writes to CRM happen:
public static class CrmTransactionQueue
{
public static object Lock { get; set; }
public static void Execute(Action<XrmServiceContext> transaction, XrmServiceContext Ctx)
{
lock (Lock)
{
transaction.Invoke(Ctx);
}
}
}
Is this sound design or there's a better way to do this ?

How to translate ReceiveReady method in NetMQ from C# to F#

I'm working with a library that does not have F# documentation, only C#. Having no familiarity with C# I'm having a bit of trouble. Reading through the documentation for NetMQ, there is one line that I'm having trouble translating:
For context, here is the full example:
using (var rep1 = new ResponseSocket("#tcp://*:5001"))
using (var rep2 = new ResponseSocket("#tcp://*:5002"))
using (var poller = new NetMQPoller { rep1, rep2 })
{
rep1.ReceiveReady += (s, a) => // ??????
{
string msg = a.Socket.ReceiveString();
a.Socket.Send("Response");
};
rep2.ReceiveReady += (s, a) => // ??????
{
string msg = a.Socket.ReceiveString();
a.Socket.Send("Response");
};
poller.Run();
}
Specifically, I don't know what rep1.ReceiveReady += (s, a) => means in the context of C# as well as how to translate it to F#. Any ideas?
Thanks.
rep.ReceiveReady += (s, a) => { /*...*/ }; is subscribing to the ReceiveReady event with a lambda function. Here is a direct F# translation:
use rep1 = new ResponseSocket("#tcp://*:5001")
use rep2 = new ResponseSocket("#tcp://*:5002")
use poller = new NetMQPoller()
poller.Add rep1
poller.Add rep2
rep1.ReceiveReady.Add (fun a -> let msg = a.Socket.ReceiveString ()
a.Socket.Send "Response")
rep2.ReceiveReady.Add (fun a -> let msg = a.Socket.ReceiveString ()
a.Socket.Send "Response")
poller.Run ()
Further reading on event handling in F# can be found in the documentation. Note, however, that F# can also treat events as observables, which is likely to be considered more idiomatic.

AllJoyn Studio - Multiple Interface Implementation

I am trying to implement an AllJoyn consumer with multiple interfaces. The AllJoyn menu creates the helper files for all the interfaces from the introspection xml. After Adding the watcher event handler and starting the same for all the interfaces only the first watcher event handler is fired and completed.
for example in the LSF introspection we have four interfaces hence:
AllJoynBusAttachment bus_Consumer = new AlljoynBusAttachment();
watcher_Consumer = new LampStateWatcher(bus_Consumer);
watcher_Consumer.Added += Watcher_Consumer_Added;
watcher_Consumer.Start();
watcher_Details = new LampDetailsWatcher(bus_Consumer);
watcher_Details.Added += Watcher_Details_Added;
watcher_Details.Start();
private async void Watcher_Details_Added(LampDetailsWatcher sender, AllJoynServiceInfo args)
{
Join_Session_Details = await LampDetailsConsumer.JoinSessionAsync(args, sender);
Consumer_Details = Join_Session_Details.Consumer;
if (Join_Session_Details.Status == AllJoynStatus.Ok)
{
var LampName = await Consumer_Details.GetLampIDAsync();
Status_List.Items.Add(LampName.LampID);
}
}
private async void Watcher_Consumer_Added(LampStateWatcher sender, AllJoynServiceInfo args)
{
Join_Session = await LampStateConsumer.JoinSessionAsync(args, sender);
Consumer_Bulb = Join_Session.Consumer;
if (Join_Session.Status == AllJoynStatus.Ok)
{
LightBulbs.Add(Consumer_Bulb);
}
Consumer_Bulb.SessionMemberRemoved += Consumer_Bulb_SessionMemberRemoved;
}
In this case only the Watcher_Consumer_Added is fired and completed where as the the Watcher_Details_Added is fired but not completed.
How can I complete both the processes. Is the above method correct to implement multiple interfaces on the consumer?
P.S. : this is using the AllJoyn Studio extension for VS2015 running on Windows10
An additional BusAttachement is required for the second watcher. A single bus cannot be shared between two watchers.
This is the answer i received on MSDN forum.
The link to the same is here
AllJoyn Studio - Multiple Interface Implementation

differentiate among multiple webclient results

There is a List.
I want to download each url via webclient.DownloadStringAsync
the problem I encounter is:
how do I know which e.Result corresponds to what url ?
public class ressource{
public string url { get; set; }
public string result { get; set; }
}
List<ressource> urlist = new List<ressource>();
urlist.Add(new ressource(){url="blabla", result=string.empty});
....etc
var wc= new WebClient();
foreach(var item in urlist)
{
wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
wc.DownloadStringAsync(new Uri(item.url, UriKind.Absolute));
}
void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
urlist[?].result = e.Result;
}
I feel completely stuck.
Thanks for your ideas.
the problem I encounter is: how do I know which e.Result corresponds to what url ?
There are various different options for this:
UserState
You can pass in a second argument to DownloadStringAsync, which is then available via DownloadStringCompletedEventArgs.UserState. For example:
// In your loop....
var wc = new WebClient();
wc.DownloadStringAsync(new Uri(item.url, UriKind.Absolute), item);
void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
var item = (ressource) e.UserState;
item.result = e.Result;
}
Multiple WebClients
You can create a new WebClient for each iteration of the loop, and attach a different event handler to it. A lambda expression is useful here:
// Note: this is broken in C# 3 and 4 due to the capture semantics of foreach.
// It should be fine in C# 5 though.
foreach(var item in urlist)
{
var wc = new WebClient();
wc.DownloadStringCompleted += (sender, args) => item.result = args.Result;
wc.DownloadStringAsync(new Uri(item.url, UriKind.Absolute));
}
DownloadStringTaskAsync
You could DownloadStringTaskAsync instead, so that each call returns a Task<string>. You could keep a collection of these - one for each element in urlist - and know which is which that way.
Alternatively, you could just fetch all the results synchronously, but I suspect you don't want to do that.
Additional information
Unfortunately, WebClient doesn't support multiple concurrent connections, so with all the options above you should create a new WebClient per iteration anyway.
Another alternative, and the one I prefer, is to use Microsoft's Reactive Framework (Rx). It handles all the background threading for you, similar to the TPL, but often easier.
Here's how I would do it:
var query =
from x in urlist.ToObservable()
from result in Observable.Using(
() => new WebClient(),
wc => Observable.Start(() => wc.DownloadString(x.url)))
select new
{
x.url,
result
};
Now to get the results back into the original urlist.
var lookup = urlist.ToDictionary(x => x.url);
query.Subscribe(x =>
{
lookup[x.url].result = x.result;
});
Simple as that.

Categories