When creating an observable from an event, it looks like the following is the most common way:
var o = Observable.FromEventPattern(h => source.Event += h,
h => source.Event -= h);
I find this form a little tedious in some cases where I would like to handle multiple events in the same way. But that doesn't look to easy, since the event it self seems impossible to parameterize, as shown in this non-compiling code:
private IObservable MakeAnObservableFromThisEvent(Event event)
{
return Observable.FromEventPattern(h => event += h,
h => event -= h);
}
private void MakeAlotOfObservables(object source)
{
MakeAnObservableFromThisEvent(source.OneEvent);
MakeAnObservableFromThisEvent(source.AnotherEvent);
MakeAnObservableFromThisEvent(source.ThirdEvent);
//or even
MakeAnObservableFromThisEvent(() => source.ThirdEvent);
}
Of cause there is the 'event name'-overload:
var o = Observable.FromEventPattern< >(source, "Event");
but then there is this thing with more or less magic strings...
Is there away of optimizing this code? Or is this just the way things are?
The problem is that event handlers have "value-type" semantics (like strings) and so passing them as parameters is only useful if you intend to invoke them. Adding new handlers effectively creates a new delegate instance and the original is not modified.
Then only really viable method to add and remove handlers and maintain type safety at the same time is with the syntax you showed first in your question.
var o =
Observable
.FromEventPattern(
h => source.Event += h,
h => source.Event -= h);
However, there is another option that I've used quite a bit - and that's using extension methods.
If I have this class:
public class Foo
{
public event EventHandler<EventArgs> Click;
}
I can write an extension method:
public static class FooEx
{
public static IObservable<EventPattern<EventArgs>> Clicks(this Foo source)
{
return
Observable
.FromEventPattern<EventArgs>(
h => source.Click += h,
h => source.Click -= h);
}
}
That then allows me to write this:
var foo = new Foo();
foo.Clicks().Subscribe(x => Console.WriteLine("Click!"));
You effectively write the extension method once per type and event and then can use it where ever you need to with a much improved syntax.
It's not really a direct solution, but the ReactiveUI-Events basically implements what #Enigmativity suggests for the entire framework. So you can do something like:
Observable.Merge(
Foo.Events().Clicked.Select(_ => Unit.Default),
Foo.Events().KeyUp.Select(_ => Unit.Default));
Related
I am developing a WPF application. User can change their Address in a form. I want to raise an event when user clicks a button (to change their address) and use the UserInfoEventArgs to process some information. I am trying to use Reactive Extensions.
MS Documentation (Subject<T> constructor)
I have two doubts. How to subscribe to mySubject and also how to add the UserInfoEventArgs to the subject.
Subject<string[]> mySubject = new Subject<string[]>();
// How to subscribe to mySubject and use the method "AddressSubscriber" as the subscriber?
private void UserDataChangedHandler (object sender, UserInfoEventArgs info)
{
string[] updatedAddress = info.NewAddress.ToArray();
if (updatedAddress.Any())
{
// How to add "updatedAddress" to mySubject so that "AddressSubscriber" can use it?
}
}
private void AddressSubscriber(string[] adrs)
{
// Do some operations with adrs
}
Use the Observable.FromEventPattern method instead of creating a superfluous Subject<T>:
Observable.FromEventPattern<RoutedEventHandler, RoutedEventArgs>(
h => btn.Click += h,
h => btn.Click -= h)
.Select(_ => new UserInfoEventArgs())
.Subscribe(args => { /* do something with the args...*/ });
How to subscribe to mySubject and use the method AddressSubscriber as the subscriber?
mySubject.Subscribe(adrs => AddressSubscriber(adrs));
How to add updatedAddress to mySubject so that AddressSubscriber can use it?
mySubject.OnNext(updatedAddress);
This question already has answers here:
C# - Event keyword advantages?
(3 answers)
Closed 6 years ago.
I detected the feature of C# that it is possible to use an Action or Func like an event. What I mean is, that I can do following:
Action aAction;
aAction = DoSomething;
aAction += DoAnotherting;
// execute the action -> both functions will be executed
aAction();
aAction -= DoSomething; // unsubscribe on function
I was not aware of this, thought using += is only possible for events. In the first moment this looks quite well, as I do not have to use the event keyword and I can also call this action from outside of the owner class (what is not possible for events).
But I'm wondering, are there any good examples for such a use or is it only bad practice?
A complete example is shown here:
[TestMethod]
public void DummyTest()
{
DummyClass myInstance = new DummyClass();
int i = 0;
Action action1 = () => i++;
Action action2 = () => i += 2;
Func<int> func1 = () => 5;
myInstance.MyFunc += () => 3;
myInstance.MyFunc += func1;
Assert.AreEqual(5, myInstance.MyFunc?.Invoke() );
myInstance.MyFunc -= func1;
Assert.AreEqual(3, myInstance.MyFunc?.Invoke() );
myInstance.MyAction = action1;
myInstance.MyAction += action2;
myInstance.MyAction?.Invoke();
Assert.AreEqual(3, i);
myInstance.MyAction -= action1;
myInstance.MyAction?.Invoke();
Assert.AreEqual(5, i);
myInstance.MyAction = () => i = 0;
myInstance.MyAction?.Invoke();
Assert.AreEqual(0, i);
}
class DummyClass
{
public Action MyAction;
public Func<int> MyFunc;
}
It is my impression that the whole point of events is to put the control of events into the enclosing type. It is not up to clients to choose when the event is fired. An event is a (collection of) function(s) that is(/are) invoked when some state is changed in a type or when something interesting happens that clients might want to react to, but the exact details should be kept hidden for the same reason that you shouldn't expose fields to clients either.
There's nothing inherently HORRIBLE with it in the sense that it's going to blow up your house, but on the other hand there is no REASON to use them like this. Events are in the language for a reason, they have semantic meaning. If you use Action/Func delegates instead of events, people who read your code will have to figure out what the heck you're doing and why you aren't using the conventional tools instead. It's just clutter/noise, so my advise is to avoid it.
Follow up to my question here:
According to a comment made -
The compiler creates a class member with a fictitious name and attaches it just as you would attach a declared method.
I do not fully comprehend what this means but I can verify that if instead of saying
Foo.Bar += (S, E) => { /*Code Goes Here*/ }
I instead say
Foo.Bar += FooBar;
private void FooBar( object sender, EventArgs e ){
/*Code Goes Here*/
}
then Event.Target changes from WhatIsThis.App.<>c to WhatIsThis.App.
That's awesome but I can't guarantee that I will always write an actual method to attach to an event handler.
In the cases where I do use an anonymous method, is there a way to extract the real target, or am I just pigeonholed into using defined methods (I mean, I can live with that I guess but if there's some high-tech sorcery that I can employ to extract the real target, then I'm all for it ).
do not fully comprehend what this means
Let's fix your comprehension. Suppose you have:
class C
{
int x;
void M(int y)
{
int z = GetZ();
Func<int, int> f = q => q + x + y + z;
...
f is a delegate. It has a receiver and a method that is a method of the receiver. (Note, this is not actually a strict requirement but the corner case is obscure for our purposes today.)
What type is the receiver that has that method?
Can it be C, with the receiver equal to this? No. Why not? Because then how do we keep track of the value of y and z? There could be a different value for every invocation of M, so the receiver cannot be this.
What the compiler does is generates a new class:
class C
{
int x;
class Locals
{
public C __this;
public int y;
public int z;
public int A(int q) { return q + __this.x + y + z; }
}
void M(int y)
{
Locals locals = new Locals();
locals.__this = this;
locals.y = y;
locals.z = GetZ();
Func<int, int> f = locals.A;
...
So what is the receiver? the value of locals. What is the method? A.
Of course both Locals and A are given crazy names so that you cannot call them by accident.
In the cases where I do use an anonymous method, is there a way to extract the real target
You are extracting the real receiver, I promise.
'm working on an extension to do some things with Event Handlers and I need to be able to discern what an event handlers target is
Please don't do that. The receiver of an event handler is an implementation detail of the code that provided the handler. It's not there for you to make decisions on. Compilers are well within their rights to make any choice they like when generating a receiver for an event handler, and they do. Consider what happens if the event handler was created inside an iterator block, or an async method, for example. Or the event is being subscribed by some reactive extensions code that is applying sequence operations to the event. Again, the compiler will be generating classes all over the place. You can't rely on the class being something "sensible".
The thing you can rely on is: the subscriber wished the given method to be called when something happened. That's the contract you must obey; don't try to second-guess the subscriber.
It's not entirely obvious to me what's happening in this situation.
I'd expect both functions to be fired.
Either the EventHander class is storing the list of functions to fire as an array - and the array is copied to a new one every time something is added/removed - or when the assignment is made, the whole thing is copied to a new "collection" - and not just a reference.
Somebody please enlighten me :D
Here's a little Linqpad script:
public class Moop
{
public EventHandler myEvent;
}
void Main()
{
var moo = new Moop();
moo.myEvent += (o, sender) => { "Added to Moop #1".Dump(); };
var moo2 = new Moop();
//Copy the reference, I assume?
moo2.myEvent = moo.myEvent;
moo2.myEvent += (o, sender) => { "Added to Moop #2".Dump(); };
//Fire the event on #1
moo.myEvent(null, null);
}
Event handler lists are delegates, and delegates are immutable -- like strings. So you do copy the delegate, and the second event handler gets "added to" the 2nd delegate, not the first.
You can find out more about delegates at http://www.c-sharpcorner.com/uploadfile/Ashush/delegates-in-C-Sharp/
Good luck!
We've got a client calling off to a TIBCO EMS queue and are wiring up the events like this:
var msgConsumer = _session.CreateConsumer(responseQueue);
var response = Observable.FromEvent<EMSMessageHandler,EMSMessageEventArgs>
(h => msgConsumer.MessageHandler += h, h => msgConsumer.MessageHandler -= h)
.Where(arg => arg.Message.CorrelationID == message.MessageID);
When I call response.Subscribe(...) I get System.ArgumentException "Error binding to target method."
I can make it work with Observable.FromEventPattern<EMSMessageEventArgs>(msgConsumer, "MessageHandler") but then it's got the event as a string and just not as clean.
Also I have IObservable<EventPattern<EMSMessageEventArgs>> rather than IObservable<EMSMessageEventArgs>
What I'd like to understand is: when should I use FromEvent over FromEventPattern? It seems a bit trial and error.
"Use FromEvent for events structurally don't look like a .NET event pattern (i.e. not based on sender, event args), and use FromEventPattern for the pattern-based ones." - Bart De Smet (Rx team)
To elaborate on this a bit further, you can typically determine when to choose one of the FromEvent vs FromEventPattern by the type of event used in the class you're trying to observe. Use FromEventPattern when your event is of type EventHandler or the generic EventHandler<T>. Use FromEvent when you're using a custom, non-generic event handler type.
The following examples are lifted directly from the Rx wiki, which has lots of good examples- 101 of them to be exact.
FromEventPattern (with generic EventHandler):
class ObserveEvent_Generic
{
public class SomeEventArgs : EventArgs { }
public static event EventHandler<SomeEventArgs> GenericEvent;
static void Main()
{
// To consume GenericEvent as an IObservable:
IObservable<EventPattern<SomeEventArgs>> eventAsObservable = Observable.FromEventPattern<SomeEventArgs>(
ev => GenericEvent += ev,
ev => GenericEvent -= ev );
}
}
FromEvent:
class ObserveEvent_NonGeneric
{
public class SomeEventArgs : EventArgs { }
public delegate void SomeNonGenericEventHandler(object sender, SomeEventArgs e);
public static event SomeNonGenericEventHandler NonGenericEvent;
static void Main()
{
// To consume NonGenericEvent as an IObservable, first inspect the type of EventArgs used in the second parameter of the delegate.
// In this case, it is SomeEventArgs. Then, use as shown below.
IObservable<IEvent<SomeEventArgs>> eventAsObservable = Observable.FromEvent(
(EventHandler<SomeEventArgs> ev) => new SomeNonGenericEventHandler(ev),
ev => NonGenericEvent += ev,
ev => NonGenericEvent -= ev);
}
}
Apparently the new syntax has changed a bit. The current syntax is the following:
// get events as observable
var events = Observable.FromEvent<MouseButtonEventHandler, MouseEventArgs>(
handler => MouseUp += handler, handler => MouseUp -= handler);
// subscribe to events
var subscription = events.Subscribe(args => OnMouseUp()));
// always dispose subscriptions!
subscription.Dispose();