I am creating an event driven class so that when I pass it a series of data, it will 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
}
Related
I have a simple delegate, event and property allowing me to create callback subscriptions on events:
public static class Test
{
/// <summary>Delegate for property changed event</summary>
public delegate void TestEventHandler();
/// <summary>Event called when value is changed</summary>
public static event TestEventHandler OnTestHappening;
/// <summary>Property to specify our test is happening</summary>
private static bool testHappening;
public static bool TestHappening
{
get
{
return testHappening;
}
set
{
testHappening = value;
// Notify our value has changed only if True
// ie. Only fire an event when we're ready as we'll hook methods to the Event that must only fire if ready
if ( value )
{
if ( OnTestHappening != null )
OnTestHappening();
}
}
}
}
I can then easily subscribe and unsubscribe to the event and fire the event callbacks as needed:
public class Tester
{
private void Main()
{
Testing();
// Start the test
Test.TestHappening = true;
}
private void Testing()
{
// Unsubscribe from event
Test.OnTestHappening -= Testing;
// Check if we're busy testing yet
if ( !Test.TestHappening )
{
// Subscribe to event
Test.OnTestHappening += new Test.TestEventHandler( Testing );
return;
}
// Do stuff here....
}
}
When compiling, code analysis gives me, "CA1009: Declare event handlers correctly?" and I've searched high and low and found many questions, articles etc but none that feel like they address my scenario. I can't seem to find a concrete starting point for the conversion and I'm starting to wonder if I'm meant to completely rewrite the implementation?
Edit: Firstly I really appreciate the assists, I did look carefully through all the sites I could before posting this and I did see (and try work with) each of the links that you all posted. I even went back and studied delegates and events again but I feel like I'm missing the starting point somehow because each time I try change a part of it, I just keep producing errors that I can't come back from like:
public delegate void TestEventHandler( object sender, EventArgs e );
With the other links I visited, I could only find 1 similarity to my code (either in the delegate, the handler or the property) but couldn't find anything that related enough to mine to actually instil that "eureka" moment
Edit 2: I have now rebuilt my example with what "looks" to be the correct standard but this code is so fugly it looks like it was beaten with a confogulus stick and dipped in a tank of confutious before being deep fried in horriduculous:
public static class Test
{
/// <summary>Delegate for property changed event</summary>
public delegate void TestEventHandler( object sender, EventArgs e );
/// <summary>Event called when value is changed</summary>
public static event TestEventHandler OnTestHappening;
/// <summary>Property to specify our test is happening</summary>
private static bool testHappening;
public static bool TestHappening
{
get
{
return testHappening;
}
set
{
testHappening = value;
// Notify our value has changed only if True
// ie. Only fire an event when we're ready as we'll hook methods to the Event that must only fire if ready
if ( value )
{
if ( OnTestHappening != null )
OnTestHappening( null, EventArgs.Empty );
}
}
}
}
public class Tester
{
private void Main()
{
Testing( this, EventArgs.Empty );
// Start the test
Test.TestHappening = true;
}
private void Testing( object sender, EventArgs e )
{
// Unsubscribe from the event
Test.OnTestHappening -= Testing;
// Check if we're busy testing yet
if ( !GlobalClass.SystemOnline )
{
// Subscribe to the event
Test.OnTestHappening += new Test.TestEventHandler( Testing );
return;
}
// Do stuff here....
}
}
Please tell me I've missed something and that there is in fact a more elegant implementation
Edit 3 : Based on the code by Enigmativity, I've reworked the code to it's most basic form. I've also moved the code setting the variable to true in a different method so it doesn't look so daft sitting in Main.
public static class Test4
{
/// <summary>Event called when value is changed</summary>
public static event EventHandler TestHappening;
/// <summary>Property to specify our test is happening</summary>
private static bool test = false;
public static bool Test
{
get
{
return test;
}
set
{
// Notify our value has changed only if True
// ie. Only fire an event when we're ready as we'll hook methods to the Event that must only fire if ready
if ( value )
{
TestHappening( null, EventArgs.Empty );
}
}
}
}
public class Tester4
{
private void Main()
{
Testing( this, EventArgs.Empty );
}
private void Testing( object sender, EventArgs e )
{
// Unsubscribe from the event
Test4.TestHappening -= Testing;
// Check if we're busy testing yet
if ( !Test4.Test )
{
// Subscribe to the event
Test4.TestHappening += Testing;
return;
}
// Do stuff here....
}
private void SomeMethodCalledFromSomewhere()
{
// Set the value to true and thereby start the test
Test4.Test = true;
}
}
Would this be considered good code or should I rather have the OnTestHappening method as defined in Enigmativity's code?
Why can't I use a parameterless delegate? It's now using the default ( object sender, EventArgs e ) but that feels overkill and doesn't make sense why the compiler is happy with it but according to coding standards it's considered bad code? I'm not arguing the standard but rather trying to understand it's reasoning.
As per Storm's request, here is how I would most likely structure the code. It's more inline with the standard conventions.
public static class TestClass
{
public delegate void TestEventHandler(object sender, EventArgs e);
public static event TestEventHandler TestHappening;
private static bool test = false;
public static bool Test
{
get
{
return test;
}
set
{
test = value;
if (test)
{
OnTestHappening();
}
}
}
private static void OnTestHappening()
{
var handler = TestHappening;
if (handler != null)
handler(null, EventArgs.Empty);
}
}
And Tester would look like this:
public class Tester
{
public void Main()
{
TestClass.TestHappening += Testing;
Go();
}
private void Testing(object sender, EventArgs e)
{
Console.WriteLine(TestClass.Test);
TestClass.TestHappening -= Testing;
}
private void Go()
{
TestClass.Test = true;
}
}
Calling it would look like this:
var tester = new Tester();
tester.Main();
Running this outputs True to the console.
If I were writing this in a more standard way, it would look like this:
public class TestEventArg : EventArgs
{
public TestEventArg(bool updatedValue)
{
this.UpdatedValue = updatedValue;
}
public bool UpdatedValue { get; private set; }
}
public class TestClass
{
public event EventHandler<TestEventArg> TestHappening;
private bool test = false;
public bool Test
{
get { return test; }
set
{
var old = test;
test = value;
if (test != old)
OnTestHappening(test);
}
}
private void OnTestHappening(bool updatedValue)
{
var handler = TestHappening;
if (handler != null)
handler(this, new TestEventArg(updatedValue));
}
}
I was writing some tests for one of my classes and I needed to test that an event was being raised. Out of just trying it and seeing what happened I coded something similar to the following extremely simplified code.
public class MyEventClass
{
public event EventHandler MyEvent;
public void MethodThatRaisesMyEvent()
{
if (MyEvent != null)
MyEvent(this, new EventArgs());
}
}
[TestClass]
public class MyEventClassTest
{
[TestMethod]
public void EventRaised()
{
bool raised = false;
var subject = new MyEventClass();
subject.MyEvent += (s, e) => raised = true;
subject.MethodThatRaisesMyEvent();
Assert.IsTrue(raised);
}
}
I wasn't so much amazed when it worked as when I started to try and figure out how it worked. Specifically, how would I write this without lambda expressions so that the local variable raised can be updated? In other words, how is the compiler refactoring/translating this?
I got this far...
[TestClass]
public class MyEventClassTestRefactor
{
private bool raised;
[TestMethod]
public void EventRaised()
{
raised = false;
var subject = new MyEventClass();
subject.MyEvent += MyEventHandler;
subject.MethodThatRaisesMyEvent();
Assert.IsTrue(raised);
}
private void MyEventHandler(object sender, EventArgs e)
{
raised = true
}
}
But this changes raised to a class-scoped field rather than a local-scope variable.
Specifically, how would I write this without lambda expressions so that the local variable raised can be updated?
You would create an extra class, to hold the captured variables. That's what the C# compiler does. The extra class would contain a method with the body of the lambda expression, and the EventRaised method would create an instance of that capturing class, using the variables within that instance instead of "real" local variables.
It's easiest to demonstrate this without using events - just a small console application. Here's the version with the lambda expression:
using System;
class Test
{
static void Main()
{
int x = 10;
Action increment = () => x++;
increment();
increment();
Console.WriteLine(x); // 12
}
}
And here's code which is similar to the code generated by the compiler:
using System;
class Test
{
private class CapturingClass
{
public int x;
public void Execute()
{
x++;
}
}
static void Main()
{
CapturingClass capture = new CapturingClass();
capture.x = 10;
Action increment = capture.Execute;
increment();
increment();
Console.WriteLine(capture.x); // 12
}
}
Of course it can get much more complicated than this, particularly if you have multiple captured variables with different scopes - but if you can understand how the above works, that's a big first step.
Compiler generates class like this, which has method with signature of lambda delegate. All captured local variables moved to this class fields:
public sealed class c_0
{
public bool raised;
public void m_1(object s, EventArgs e)
{
// lambda body goes here
raised = true;
}
}
And final compiler trick is replacing usages of local raised variable with this field of generated class:
[TestClass]
public class MyEventClassTest
{
[TestMethod]
public void EventRaised()
{
c_0 generated = new c_0();
generated.raised = false;
var subject = new MyEventClass();
subject.MyEvent += generated.m_1;
subject.MethodThatRaisesMyEvent();
Assert.IsTrue(generated.raised);
}
}
I'm trying to expose an API such that, I do the following
RegisterCallback<T>(Action<T> func)
{
someObj.FuncPointer = func;
}
Later on, I call func(obj) .. and the obj is of type T that the user said.
More concrete example:
var callbackRegistrar = new CBRegistrar();
callbackRegistrar.RegisterCallback<ISomeClass>(SomeFunc);
public static void SomeFunc(ISomeClass data)
{
//
}
EDIT: So I may not have been clear, so I'll add more code:
I want to make only "one" object of CBRegistrar, and connect it with many Callbacks, as such:
var callbackRegistrar = new CBRegistrar();
callbackRegistrar.RegisterCallback<ISomeClass>(SomeFunc);
callbackRegistrar.RegisterCallback<ISomeOtherClass>(SomeFunc2);
...
In fact the above code is called by reflecting over a directory of plugins.
The user puts this in their code -->
public static void SomeFunc(ISomeClass data)
{
//
}
public static void SumFunc2(ISomeOtherClass data)
{
//
}
It looks to me as if this is not possible using Generics, etc. What it looks like I might have to do is make an interface called IPlugin or something, and ask the user to do this ..
[PluginIdentifier(typeof(ISomeClass))]
public static void SomeFunc(IPluginData data)
{
var castedStuff = data as ISomeClass; // ISomeClass inherits from IPluginData
}
Seems like asking the user to do stuff that we should take care of, but anyway ...
You need a Action<T> func to store it in. There is a semantic check to make here: if someone calls RegisterCallback twice (with different values), do you want to replace the callback, or keep both ? Assuming the latter, someObj probably wants an event (indeed, this entire API could be exposed as an event), so - in the someObj class:
public event Action<T> FuncPointer;
private void InvokeCallback(T data) {
var handler = FuncPointer;
if(handler != null) handler(data);
}
Noting that RegisterCallback could be replaced entirely, still keeping the data on obj:
public event Action<T> Completed {
add { obj.FuncPointer += value; }
remove { obj.FuncPointer -= value; }
}
Then usage would be:
var callbackRegistrar = new CBRegistrar();
callbackRegistrar.Completed += SomeFunc;
Callback functions are not much used in C#. They've been replaced by events which are more elegant and easier to work with.
class CBRegistrar
{
public delegate void ActionRequiredEventHandler(object sender, ISomeClass e);
public event ActionRequiredEventHandler ActionRequired;
void RaiseActionRequiredEvent(ISomeClass parm)
{
if ( ActionRequired != null)
{
ActionRequired(this, parm);
}
}
}
class APIConsumer
{
var callbackRegistrar = new CBRegistrar();
public APIConsumer()
{
callbackRegistrar.ActionRequired += SomeFunc;
}
public void SomeFunc(object sender, ISomeClass data)
{
}
}
If you still want to use Callbacks, you can use Delegates which are more or less function pointer.
The CBRegistrar will need to be generic (if it's OK to keep a single callback type) or it can do some internal casting (if several callback types need to be registered).
public class CBRegistrar<T>
{
private Action<T> callback;
private Dictionary<Type, object> callbackMap;
public CBRegistrar()
{
this.callbackMap = new Dictionary<Type, object>();
}
public void RegisterCallback(Action<T> func)
{
this.callback = func;
}
public void RegisterGenericCallback<U>(Action<U> func)
{
this.callbackMap[typeof(U)] = func;
}
public Action<U> GetCallback<U>()
{
return this.callbackMap[typeof(U)] as Action<U>;
}
}
public interface ISomeClass
{
string GetName();
}
public class SomeClass : ISomeClass
{
public string GetName()
{
return this.GetType().Name;
}
}
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
var callbackRegistrar = new CBRegistrar<ISomeClass>();
callbackRegistrar.RegisterCallback(SomeFunc);
callbackRegistrar.RegisterGenericCallback<ISomeClass>(SomeFunc);
var someone = new SomeClass();
callbackRegistrar.GetCallback<ISomeClass>()(someone);
}
public static void SomeFunc(ISomeClass data)
{
// Do something
Console.WriteLine(data.GetName());
}
}
}
I am not sure if I understood the usage of delegates correctly but I would like to read delegate return value in publisher class. The example is below with description.
//Publisher class
public class ValidateAbuse
{
public delegate List<String> GetAbuseList();
public static GetAbuseList Callback;
public void Ip(string ip)
{
// I would like to read GetAbuseList value (List<String>) here. How to do that?
}
}
//Subscriber class
class Server
{
public static void Start()
{
ValidateAbuse.Callback = GetIpAbuseList;
ValidateAbuse.Ip(MyIp);
}
private static List<string> GetIpAbuseList()
{
//return List<String> to ValidateAbuse class and use return value in public void Ip(string ip) method
}
public void Ip(string ip)
{
if (Callback != null)
{
List<String> valueReturnedByCallback = Callback();
}
}
Here's a version that does not use static for ValidateAbuse and that uses the built-in Func<T> delegate.
public class ValidateAbuse
{
private Func<List<string>> callback;
public ValidateAbuse(Func<List<string>> callback)
{
this.callback = callback;
}
public void Ip(string ip)
{
var result = callback();
}
}
public class Server
{
public static void Start()
{
var validateAbuse = new ValidateAbuse(GetIpAbuseList);
validateAbuse.Ip(MyIp);
}
private static List<string> GetIpAbuseList()
{
//return List<string> to ValidateAbuse class and use return value in public void Ip(string ip) method
}
}
I recommend you avoid static since that gives you a global state, which could later give you coupling problems and also makes it hard for you to unit test.
The other answers given so far has a guard clause, checking Callback for null. Unless that is expected behaviour (that Callback is null) I would avoid this. It's better to crash early than to get hard to debug errors later on.
I would also try to make the Server non-static.
It should be as simple as:
// Ip in your code sample is missing static
public static void Ip(string ip)
{
List<string> abuseList;
if (Callback != null)
abuseList = Callback()
}
However you can avoid creating a delegate all together by using a Func:
public static Func<List<string>> Callback;
Try this: Read more from here http://msdn.microsoft.com/en-us/library/bb534960%28v=vs.110%29.aspx
internal delegate int PowerOfTwo();
void Main(){
PowerOfTwo ch = new PowerOfTwo(CheckPower);
Console.WriteLine(ch());
}
int CheckPower(){
return 2*2;
}
#Torbjörn Kalin's answer is good, but only if you have only 1 delegate you want to get the return value from. If you want to retrieve the return values of more than one delegate, this is how you do it:
//Publisher class
public class ValidateAbuse
{
public delegate List<String> GetAbuseList();
public static GetAbuseList Callback;
public void Ip(string ip)
{
foreach (GetAbuseList gal in Callback.GetInvocationList())
{
List<string> result = gal.Invoke(/*any arguments to the parameters go here*/);
//Do any processing on the result here
}
}
}
//Subscriber class
class Server
{
public static void Start()
{
//Use += to add to the delegate list
ValidateAbuse.Callback += GetIpAbuseList;
ValidateAbuse.Ip(MyIp);
}
private static List<string> GetIpAbuseList()
{
//return code goes here
return new List<String>();
}
This will invoke each delegate one after the other, and you can process the output of each delegate separately from each other.
The key here is using the += operator (not the = operator) and looping through the list that is retrieved by calling GetInvocationList() and then calling Invoke() on each delegate retrieved.
I figured this out after reading this page:
https://www.safaribooksonline.com/library/view/c-cookbook/0596003390/ch07s02.html
(altho it was partially because I already had an idea what to do, and I didn't start a free trial to read the rest)
Hope this helps!
This would be the first time I'd use delegates in c# so please bear with me. I've read a lot about them but never thought of how/why to use this construct until now.
I have some code that looks like this:
public class DoWork()
{
public MethodWorkA(List<long> TheList) {}
public void MethodWork1(parameters) {}
public void MethodWork2(parameters) {}
}
I call MethodWorkA from a method outside the class and MethodWorkA calls MethodWork 1 and 2. When I call methodA, I'd like to pass some sort of parameter so that sometimes it just does MethodWork1 and sometimes it does both MethodWork1 and MethodWork2.
So when I call the call it looks like this:
DoWork MyClass = new DoWork();
MyClass.MethodA...
Where does the delegate syntax fit in this?
Thanks.
public void MethodWorkA(Action<ParamType1, ParamType2> method) {
method(...);
}
You can call it using method group conversion:
MethodWorkA(someInstance.Method1);
You can also create a multicast delegate that calls two methods:
MethodWorkA(someInstance.Method1 + someInstance.Method2);
For what you described, you don't need delegates.
Just do something like this:
public class DoWork
{
public void MethodWorkA(List<long> theList, bool both)
{
if (both)
{
MethodWork1(1);
MethodWork2(1);
}
else MethodWork1(1);
}
public void MethodWork1(int parameters) { }
public void MethodWork2(int parameters) { }
}
If you're just experimenting with delegates, here goes:
public partial class Form1 : Form
{
Func<string, string> doThis;
public Form1()
{
InitializeComponent();
Shown += Form1_Shown;
}
void Form1_Shown(object sender, EventArgs e)
{
doThis = do1;
Text = doThis("a");
doThis = do2;
Text = doThis("a");
}
string do1(string s)
{
MessageBox.Show(s);
return "1";
}
string do2(string s)
{
MessageBox.Show(s);
return "2";
}
}
Considering that all methods are inside the same class, and you call MethodWorkA function using an instance of the class, I honestly, don't see any reason in using Action<T> or delegate, as is I understood your question.
When I call methodA, I'd like to pass some sort of parameter so that
sometimes it just does MethodWork1 and sometimes it does both
MethodWork1 and MethodWork2.
Why do not just pass a simple parameter to MethodWorkA, like
public class DoWork()
{
public enum ExecutionSequence {CallMethod1, CallMethod2, CallBoth};
public MethodWorkA(List<long> TheList, ExecutionSequence exec)
{
if(exec == ExecutionSequence.CallMethod1)
MethodWork1(..);
else if(exec == ExecutionSequence.CallMethod2)
MethodWork2(..);
else if(exec == ExecutionSequence.Both)
{
MethodWork1(..);
MethodWork2(..);
}
}
public void MethodWork1(parameters) {}
public void MethodWork2(parameters) {}
}
Much simplier and understandable for your class consumer.
If this is not what you want, please explain.
EDIT
Just to give you an idea what you can do:
Example:
public class Executor {
public void MainMethod(long parameter, IEnumerable<Action> functionsToCall) {
foreach(Action action in functionsToCall) {
action();
}
}
}
and in the code
void Main()
{
Executor exec = new Executor();
exec.MainMethod(10, new List<Action>{()=>{Console.WriteLine("Method1");},
()=>{Console.WriteLine("Method2");}
});
}
The output will be
Method1
Method2
In this way you, for example, can push into the collection only functions you want to execute. Sure, in this case, the decision logic (which functions have to be executed) is determined outside of the call.