In my WP8 C#/XAML project I'm using events to notify my view that some async process is done.
I have two types of delegates.
I'm creating events from those delegates and there are several of them notifying my view that some operations are completed or started (in order to show progressbar, navigate to another page, disable some controls et cetera).
In order to raise these events I want to create a private "notification method", which would raise those delegates.
The method i have in mind is in Code Sample below as fireUpEvent
method.
ReturnState enum
public enum ReturnState : int
{
state1 = 0,
... //for the purpose of the presentation
state6 = 15
...
}
Definitions of events & methods
public delegate void LoadingStartedEventHandler();
public delegate void LoadingFinishedEventHandler(ReturnState state);
public event LoadingStartedEventHandler LoadingStarted;
public event LoadingFinishedEventHandler LoadingFinished;
private void fireUpEvent(Action<ReturnState> action, Returnstate parameter)
{
if(action != null)
{
action(parameter);
}
}
private void fireUpEvent(Action action)
{
if(action != null)
{
action();
}
}
Usage
fireUpEvent(LoadingFinished, ReturnState.state1);
The problem is, that when I try to compile I get an error saying:
Argument1: Cannot convert from 'XXXX.YYYY.SomeClass.LoadingFinishedEventHandler' to 'System.Action<XXXX.YYYY.Returnstate>'
I've tried googling, but haven't found any usefull stuff.
Why isn't it convertible?
I'd like to Action<ReturnState>
and Action
in those methods instead of specific delegates, is it possible?
Should I use any other "type" like Action
instead?
The only two I know from this "grooup" are Func
& Action
, are there others?
To answer this line:
Why isn't it convertible?
They're different delegate types, and there's no reference conversion between different delegate types (other than in generic delegate types using generic variance). You can create an Action
from a LoadingStartedEventHandler
like this:
LoadingStartedEventHandler handler = ...; // Whatever
Action action = new Action(handler);
... and you could do the same the other way round, and with your other delegate type and Action<T>
. But there's really no need to do that.
I'd like to
Action<ReturnState>
andAction
in those methods instead of specific delegates, is it possible?
Yes - just don't declare the events using those delegates, and indeed don't declare the delegates at all!
You can change this:
public delegate void LoadingStartedEventHandler();
public delegate void LoadingFinishedEventHandler(ReturnState state);
public event LoadingStartedEventHandler LoadingStarted;
public event LoadingFinishedEventHandler LoadingFinished;
To this:
public event Action LoadingStarted;
public event Action<ReturnState> LoadingFinished;
Note that this violates the .NET conventions on events, mind you. By convention, events are declared with a delegate where the first parameter is the "sender", of type object
, and the second parameter is of a type derived from EventArgs
(or EventArgs
itself). Whether or not that's important to you is for you to decide. If you decide to follow the convention, you'd basically want to create a type deriving from EventArgs
holding a ReturnState
, and then replace the events with:
public event EventHandler LoadingStarted;
public event EventHandler<ReturnStateEventArgs> LoadingFinished;
And change your helper methods to:
private void RaiseEvent(EventHandler<TEventArgs> handler,
TEventArgs parameter)
{
if(handler != null)
{
handler(this, parameter);
}
}
private void RaiseEvent(EventHandler handler)
{
if(handler != null)
{
handler(this, EventArgs.Empty);
}
}
(I've modified the method names to follow .NET conventions and use the .NET terminology for events, which are "raised" rather than "fired up".)
Mr. Skeet always make good answers. Here I'm providing another solution of what you stated in the question.
For these two:
- Why isn't it convertible?
- I'd like to Action and Action in those methods instead of specific delegates, is it possible?
Mr. Skeet has already answered.
For these two:
- Should I use any other "type" like Action instead?
- The only two I know from this "grooup" are Func & Action, are there others?
Your fireUpEvent
method probably should not accept an arbritary type of delegate as a brittle design. But it is possible to do.
The ultimate base type of all delegate type in C# is Delegate
; a limitation of Delegate
is that it cannot be a where
constraint in generic types and methods.
To answer the question(regardless of the concerning of design), you can say:
private void fireUpEvent(
Delegate loadingEvent, ReturnState? parameter=null) {
if(null!=loadingEvent) {
foreach(var d in loadingEvent.GetInvocationList()) {
var args=null!=parameter?new object[] { parameter }:null;
d.Method.Invoke(d.Target, args);
}
}
}
instead of the original two methods in your question, where the Target
is the object which owns the method, would be treated as this
, null
if it's a static method. args
is the argument list passing to the method.
This is just a way that you can achieve it, and I'm pretty sure Mr. Skeet's answer is absolutely better.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With