Event driven classes in C#
I am creating an event driven class so that when I pass it a series of data, it wi开发者_运维问答ll process and then return the value when ready.
Below is the code that I am currently using the below code however it is quite nasty and I'm not sure if can be simpler than this.
public delegate void MyEventHandler(double result);
public static MyEventHandler EventComplete;
public static void MakeSomethingHappen(double[] data)
{
ThreadPool.QueueUserWorkItem(DoSomething, data);
}
private static void DoSomething(object dblData)
{
InvokeEventComplete(AndSomethingElse((double[])dblData));
}
private static void InvokeEventComplete(double result)
{
if (EventComplete != null)
{
EventComplete(result);
}
}
public static double AndSomethingElse(double[] data)
{
//do some code
return result; //double
}
In my main class I simply hook up a method to the event like so,
MyClass.EventComplete += new MyClass.EventCompleteHandler(MyClass_EventComplete);
Here you are:
- Exposed event as an actual event rather than a publicly accessible member delegate.
- Eliminated extra delegate declaration and used generic delegate Action.
- Eliminated extra invocation function which was simply verbose.
- Used lambda expression for event registration.
Edited code is:
MyClass.EventComplete += (result) => Console.WriteLine("Result is: " + result);
public class MyClass
{
public static event Action<double> EventComplete;
public static void MakeSomethingHappen(double[] data)
{
ThreadPool.QueueUserWorkItem(DoSomething, data);
}
private static void DoSomething(object dblData)
{
var result = AndSomethingElse((double[])dblData);
if (EventComplete != null)
{
EventComplete(result);
}
}
public static double AndSomethingElse(double[] data)
{
//do some code
return result; //double
}
}
Some things to consider...
There's an EventHandler<T> where T : EventArgs
in .NET, but the trade off is you end up writing a custom EventArgs to pass your double data instead of a custom delegate. Still I think that's a cleaner pattern to follow.
If you were to define your event as
public static MyEventHandler EventComplete = delegate {};
//using a no-op handler like this has implications on Garbage Collection
Does using a no-op lambda expression for initializing an event prevent GC?
you could save yourself the if(EventComplete != null) check everytime and hence make the Invoke... method redundant.
you can also simplify
MyClass.EventComplete += new MyClass.EventCompleteHandler(MyClass_EventComplete);
to
MyClass.EventComplete += MyClass_EventComplete;
Aside from that it looks fine. I presume all the static
's around the code are just from working in a ConsoleApplication :-)
try using standart event pattern (thousands times used inside FCL)
// in [CompleteEventArgs.cs] file
public class CompleteEventArgs : EventArgs {
private readonly double _result;
public CompleteEventArgs(double result) {
_result = result;
}
public double Result {
get { return _result; }
}
}
// inside your class
// don't forget 'event' modifier(!) it prevents lots of illegal stuff
// like 'Complete = null' on the listener side
public static event EventHandler<CompleteEventArgs> Complete;
public static void MakeSomethingHappen(double[] data) {
ThreadPool.QueueUserWorkItem(DoSomething, data);
}
private static void DoSomething(object dblData) {
OnComplete(new CompleteEventArgs(AndSomethingElse((double[])dblData)));
}
// if you're working with a 'normal' (non-static) class
// here should be 'protected virtual' modifiers to allow inheritors
// use polymorphism to change the business logic
private static void OnComplete(CompleteEventArgs e) {
if (Complete != null)
Complete(null, e); // in 'normal' way here stands 'this' instead of 'null'
// this object (link to the sender) is pretty tricky
// and allows extra flexibility of the code on the listener side
}
public static double AndSomethingElse(double[] data) {
double result = 0;
//do some code
return result; //double
}
精彩评论