I'm probably totally misunderstanding what RX is all about, but I thought it would be a neat way of allowing various client applications in my code to subscribe to notifications of changes to certain Entity Framework Code First types.
So in my UOW Commit methood I have
var changes = DbContext.ChangeTracker.Entries<EntEvent>().Where(ee => ee.State != EntityState.Unchanged);
Hub.Instance.NotifyBeforeSave(changes);
and my (rather basic) hub class looks like this...
public sealed class Hub
{
private static readonly Hub instance = new Hub();
static Hub(){}
private Hub(){}
public static Hub Instance
{
get { return instance; }
}
public IObservable<System.Data.Entity.Infrastructure.DbEntityEntry<EntEvent>> BeforeSave = new Subject<DbEntityEntry<EntEvent>>();
public void NotifyBeforeSave<T>(IEnumerable<System.Data.Entity.Infrastructure.DbEntityEntry<T>> changes) where T:class
{
var x = changes.Where(c => typeof(T) == typeof(EntEvent)) as IEnumerable<System.Data.Entity.Infrastructure.DbEntityEntry<EntEvent>>;
BeforeSave = x.ToObservable();
}
}
and then I thought I could subscribe a client (observer) by creating an instance of the following and calling attach.
public class SampleConsumer : IObserver<DbEntityEntry<EntEvent>>
{
public void attach()
{
Hub.Instance.BeforeSave.Subscribe(this);
}
public void OnNext(DbEntityEntry<EntEvent> value)
{
var x = value;
}
public void OnError(Exception error)
{
var y = error;
}
public void OnCompleted()
{
}
}
but breakpoints in OnNext and OnError never get called.
I'm probably 180deg away from where I should be, but we have to start somewhere!
The problem is that you don't have an asynchronous source.
DbContext.ChangeTracker.Entries<EntEvent>()
is a collection. You can convert it to an observable using
IEnumerble.ToObservable();
but that does not make it asynchronous. In fact, it will enumerate the collection right away upon subscription. If the collection happens to be empty, it will do nothing at all. Google the difference between cold/hot observables to understand.
You need an asynchronous source, something like an event.
I don't know EF very well, my guess is that the
((IObjectContextAdapter)DbContext).ObjectContext.SavingChanges
event might be what you need.
Good luck!
Plug in Nick's
https://github.com/NickStrupat/EntityFramework.Triggers
https://github.com/NickStrupat/EntityFramework.Rx
He has patterns with and without deriving from his context, that permit:
DbObservable<Context>.FromInserted<Person>();
Related
I am learning WPF and MVVM at the moment and I faced a problem when i tried to write unit tests for a viewmodel, whose commands invoke async methods. That problem is well-described in this question. That question also has a solution: to write a new Command class with an additional awaitable method that can be awaited in unit tests. But since i use MvvmLight, i decided not to write a new class, but to inherit from the built-in RelayCommand class instead. However, i don't seem to understand how to do it properly. Below is a simplified example that illustrates my problem:
AsyncRelayCommand:
public class AsyncRelayCommand : RelayCommand
{
private readonly Func<Task> _asyncExecute;
public AsyncRelayCommand(Func<Task> asyncExecute)
: base(() => asyncExecute())
{
_asyncExecute = asyncExecute;
}
public AsyncRelayCommand(Func<Task> asyncExecute, Action execute)
: base(execute)
{
_asyncExecute = asyncExecute;
}
public Task ExecuteAsync()
{
return _asyncExecute();
}
//Overriding Execute like this fixes my problem, but the question remains unanswered.
//public override void Execute(object parameter)
//{
// _asyncExecute();
//}
}
My ViewModel (based on the default MvvmLight MainViewModel):
public class MainViewModel : ViewModelBase
{
private string _welcomeTitle = "Welcome!";
public string WelcomeTitle
{
get
{
return _welcomeTitle;
}
set
{
_welcomeTitle = value;
RaisePropertyChanged("WelcomeTitle");
}
}
public AsyncRelayCommand Command { get; private set; }
public MainViewModel(IDataService dataService)
{
Command = new AsyncRelayCommand(CommandExecute); //First variant
Command = new AsyncRelayCommand(CommandExecute, () => CommandExecute()); //Second variant
}
private async Task CommandExecute()
{
WelcomeTitle = "Command in progress";
await Task.Delay(1500);
WelcomeTitle = "Command completed";
}
}
As far as i understand it, both First and Second variants should invoke different constructors, but lead to the same result. However, only the second variant works the way i expect it to. The first one behaves strangely, for example, if i press the button, that is binded to Command once, it works ok, but if i try to press it a second time a few seconds later, it simply does nothing.
My understanding of async and await is far from complete. Please explain me why the two variants of instantiating the Command property behave so differently.
P.S.: this behavior is noticeable only when i inherit from RelayCommand. A newly created class that implements ICommand and has the same two constructors works as expected.
OK, I think I found the problem. RelayCommand uses a WeakAction to allow the owner (target) of the Action to be garbage collected. I'm not sure why they made this design decision.
So, in the working example where the () => CommandExecute() is in the view model constructor, the compiler is generating a private method on your constructor that looks like this:
[CompilerGenerated]
private void <.ctor>b__0()
{
this.CommandExecute();
}
Which works fine because the view model is not eligible for garbage collection.
However, in the odd-behavior example where the () => asyncExecute() is in the constructor, the lambda closes over the asyncExecute variable, causing a separate type to be created for that closure:
[CompilerGenerated]
private sealed class <>c__DisplayClass2
{
public Func<Task> asyncExecute;
public void <.ctor>b__0()
{
this.asyncExecute();
}
}
This time, the actual target of the Action is an instance of <>c__DisplayClass2, which is never saved anywhere. Since WeakAction only saves a weak reference, the instance of that type is eligible for garbage collection, and that's why it stops working.
If this analysis is correct, then you should always either pass a local method to RelayCommand (i.e., do not create lambda closures), or capture a (strong) reference to the resulting Action yourself:
private readonly Func<Task> _asyncExecute;
private readonly Action _execute;
public AsyncRelayCommand(Func<Task> asyncExecute)
: this(asyncExecute, () => asyncExecute())
{
}
private AsyncRelayCommand(Func<Task> asyncExecute, Action execute)
: base(execute)
{
_asyncExecute = asyncExecute;
_execute = execute;
}
Note that this actually has nothing to do with async; it's purely a question of lambda closures. I suspect it's the same underlying issue as this one regarding lambda closures with Messenger.
In Dustin Campbell's answer in question Return a value from a Event — is there a Good Practice for this? it is stated that instead of returning data from an event handler, we can have a writable property on a set of custom EventArgs that is passed to the event similar to Cancel property of the WinForms FormClosing event.
How do I provide feedback to event caller using properties in EventArgs?
My specific scenario is that there is a Controller class that does Job A and there are many classes requesting the Job A to be done. Thus, the controller is subscribed to this event on all classes.
I want to give some feedback to the caller that the job is done. The tricky part is that those classes are module-like and controller doesn't know anything about them.
My though is to include that writable property to the delegate of the event in order for the controller to give feedback through it. This property could somehow be invoked using reflection, which is fine in my scenario.
you cannot define properties for delegates.
Also you do not need reflection for such a mechanism.
What you want to do is to define your "return"-properties in the EventArgs-derived class.
A simple such class would be:
public class JobEventArgs : EventArgs {
public bool Done { get; set; }
}
Now you can declare your event in the class as
public event EventHandler<JobEventArgs> Job;
Usage in the method which handles the event:
public void DoJob(object s, JobEventArgs args) {
// do stuff
args.Done = true;
}
and in the event invoking code:
public void FireJobEvent() {
var args = new JobEventArgs();
this.Job(this, args);
if(!args.Done) {
// the job was not handled
}
}
But frankly it rather seems like you want to do a job asynchronously with a notification when it finishes.
Which would result in syntax like..
class Module {
public void JobCompleted(IAsyncResult r) {
if(!r.IsCompleted)
return;
Console.WriteLine("The job has finished.");
}
public void ExecuteJob() {
var job = new EventArgs<JobEventArgs>((s, a) => { this.controller.JobA(); });
job.BeginInvoke(null, null,
r =>
{
this.JobCompleted(r);
if(r.IsCompleted)
job.EndInvoke(r);
}, null);
}
}
I want to add more functionality to a project I have that makes use a number of classes packaged in the NET Framework. These same classes provide a number of properties which can be quite useful adapting the functionality of my project, however one thing that these classes lack is Events.
If each property had a appropriate event that would fire whenever the value of such property changed, I could then assign a event handler that would act based on those properties value.
I made a sample case bellow to illustrate my goal in the most simpler way I could think off.
Sample case:
The System.Net.Sockets.Socket class (Socket on MSDN Docs) has a property
named Connected that basically returns true if the socket is
connected to a specified end point otherwise returns false.
What I would like to accomplish is simple. I would like to keep this
property under "watch" and when the value of it changes, fire a event.
Doing that to one of my own classes it would be simple although a bit tiresome using the INotifyPropertyChanged interface, simply because always that my code changed the value of the property I would have to fire the event manually. Unfortunately, to best of my knowledge, not even this kind of procedure can be applied to the existing Socket class distributed within NET Framework.
Well, this question is becoming quite extensive, sorry, but I hope it gave an insight to my goal.
Now simply putting it, I want to watch the Connected property of the Socket class and when the value of it changes, fire an event. And if it would be possible to also use such approach to watch variables as well properties, it would be awesome, not just for me, but for everyone who stumbles across this question on SO.
A simple and lightweight approach is preferred of course, but most of all, I want to understand how it can be done, so in the future I can apply it in mass scale to other classes.
I realize I'm asking a lot. Many thanks.
Any questions just ask.
I implemented a basic class that should get you started. I'm sure a fully functional, production-ready, thread-safe class would require a bit more work, plus you need to implement your own strategy for when to poll for value changes.
public class TargettedObserver<T>
{
private static readonly EqualityComparer<T> EqualityComparer = EqualityComparer<T>.Default;
private Func<T> ValueTarget;
private T OldValue;
public event ObservedValueChangedEventHandler<T> ValueChanged;
public TargettedObserver(Func<T> valueTarget)
{
this.ValueTarget = valueTarget;
OldValue = ObtainCurrentValue();
}
public bool CheckValue()
{
T oldValue = OldValue;
T newValue = ObtainCurrentValue();
bool hasValueChanged = CompareValues(oldValue, newValue);
if (hasValueChanged)
{
OldValue = newValue;
NotifyValueChanged(oldValue, newValue);
}
return hasValueChanged;
}
private void NotifyValueChanged(T oldValue, T newValue)
{
var valueChangedEvent = ValueChanged;
if (valueChangedEvent != null)
valueChangedEvent(this, new ObservedValueChangedEventArgs<T>(oldValue, newValue));
}
private static bool CompareValues(T oldValue, T newValue)
{
return !EqualityComparer.Equals(oldValue, newValue);
}
private T ObtainCurrentValue()
{
return ValueTarget();
}
}
And the event handling:
public class ObservedValueChangedEventArgs<T> : EventArgs
{
public T OldValue { get; private set; }
public T NewValue { get; private set; }
public ObservedValueChangedEventArgs(T oldValue, T newValue)
{
this.OldValue = oldValue;
this.NewValue = newValue;
}
}
public delegate void ObservedValueChangedEventHandler<T>(TargettedObserver<T> observer, ObservedValueChangedEventArgs<T> eventArgs);
Usage looks something like this:
public class TestClass
{
private Socket MySocket;
private static TargettedObserver<bool> SocketConnectedObserver;
public void Main()
{
MySocket = new Socket();
SocketConnectedObserver = new TargettedObserver<bool>(() => MySocket.Connected);
SocketConnectedObserver.ValueChanged += ReportSocketConnectedStateChanged;
PerformSocketConnection();
MainThread.Invoke(PollSocketValue);
}
private void PollSocketValue()
{
SocketConnectedObserver.CheckValue();
MainThread.Invoke(PollSocketValue);
}
private void ReportSocketConnectedStateChanged(TargettedObserver<bool> observer, ObservedValueChangedEventArgs<bool> eventArgs)
{
Console.WriteLine("Socket connection state changed! OldValue: " + eventArgs.OldValue + ", NewValue: " + eventArgs.NewValue);
}
}
Notice the constructor takes a simple lambda expression that can evaluate the value you're wanting to observe.
Also note that MainThread.Invoke is just a pseudocode to show it polling for a change on every main thread loop. I'm sure there are nicer strategies (background thread with a timer interval) for example that could be implemented in a nice, reusable way. Still more work to be done in terms of deregistering the observer. Could probably make some nice factory methods or lambda delegates so you don't need to keep the TargettedObserver instance floating around and reduce the amount of wiring/manual code. But at least this should be a start.
What your looking for is an implementation of the Observer Pattern. Something like this Observable<T> implementation might work.
See also the IObserver<T> Interface in .NET 4:
The IObserver<T> and IObservable<T> interfaces provide a generalized
mechanism for push-based notification. The IObservable<T> interface represents the class that
sends notifications (the provider); the IObserver<T> interface
represents the class that receives them (the observer). T represents
the class that provides the notification information.
Say I have a factory method that churns out instances of type T, and I want an Rx observable sequence for events fired from all my instances originating out of the factory method.
Is using Merge() as I have done below the correct and optimal way to achieve this?
The other way I did this was to use a static event and make the observable sequence out of that, however I generally don't like using static events and am curious what any Rx experts think would be optimal in this situation?
public T MakeFoo<T>() where T: Foo, new()
{
this.instanceOfObservable.Merge(new T());
return self;
}
public class ObservableSequence : IObservable<EventArgs>, IDisposable
{
private IObservable<EventArgs> stream;
public ObservableSequence()
{
}
// this method is called in the factory method for each new instance of T
public void Merge(Foo instance)
{
if (this.stream == null)
{
this.stream = Init(instance);
}
else
{
IObservable<EventArgs> next = Init(instance);
this.stream.Merge(next);
}
}
private IObservable<EventArgs> Init(Foo instance)
{
return Observable.FromEvent
<EventHandler<EventArgs>, EventArgs>(handler =>
{
EventHandler<EventArgs> eh = (sender, e) => {
handler(e);
};
return eh;
},
eh => instance.SomeEvent += eh ,
eh => instance.SomeEvent -= eh )
.Repeat()
.Retry()
.Publish()
.RefCount();
}
public void Dispose()
{
}
public IDisposable Subscribe(IObserver<EventArgs> observer)
{
return stream.Subscribe(observer);
}
}
Abusing Merge like that is not very efficient. The most straightforward way is via a Subject, which is an IObservable you control by hand.
public static class MyAwesomeFooFactory
{
readonly static Subject<SomeEventArgs> someEvents = new Subject<SomeEventArgs>();
public static IObservable<SomeEventArgs> NotificationsFromAllTheEvents { get { return someEvent; }}
public static Foo MakeANewFoo()
{
var ret = new Foo();
ret.SomeEvent.Subscribe(someEvents); // NB: We never unsubscribe, *evar*
return ret;
}
}
That is unlikely to work as you want, and has potentially stack-breaking performance issues. For every instance you add, you add another call to the stack between the first instance and the final observer. Get too many instances and you could blow the stack.
More important is the potentially wrong functionality. Does an observer expect to get notifications from all Foos created after it subscribes? In your current design they will not. If they should get notifications, you should change stream to a Subject<EventArgs> and have it subscribe to each Foo. The subject will serve as a merge point with the benefit that all of the subscribers to the subject will get the messages from instances created after the observer subscribed.
I have a series of modules that use a RX publish/subscribe model.
Here is the event registration code (repeated per subscribing module):
_publisher.GetEvent<DataEvent>()
.Where(sde => sde.SourceName == source.Name)
.ObserveOn(Scheduler.TaskPool)
.Subscribe(module.OnDataEvent);
The publisher is simple, thanks to José Romaniello's code:
public class EventPublisher : IEventPublisher
{
private readonly ConcurrentDictionary<Type, object> _subjects =
new ConcurrentDictionary<Type, object>(); public IObservable<TEvent> GetEvent<TEvent>()
{
var subject = (ISubject<TEvent>)_subjects.GetOrAdd(typeof(TEvent), t => new Subject<TEvent>());
return subject.AsObservable();
}
public void Publish<TEvent>(TEvent sampleEvent)
{
object subject;
if (_subjects.TryGetValue(typeof(TEvent), out subject))
{
((ISubject<TEvent>)subject).OnNext(sampleEvent);
}
}
}
Now my problem: As you can see above I used the .ObserveOn(Scheduler.TaskPool) method to spin off a new thread from the pool for every module, for every event. This is becuase I have lots of events and modules. The problem, of course, is that the events get mixed up in time order, as some events get fired close to each other and then end up calling the OnDataEvent callback in the wrong order (Each OnDataEvent carries a timestamp).
Is there a simple way to use RX to ensure the correct order of events? Or could I write my own Scheduler to ensure each module gets the events in sequence?
The events are published in the correct sequence, of course.
Thanks in advance.
Try using this implementation of the EventPublisher:
public class EventPublisher : IEventPublisher
{
private readonly EventLoopScheduler _scheduler = new EventLoopScheduler();
private readonly Subject<object> _subject = new Subject<object>();
public IObservable<TEvent> GetEvent<TEvent>()
{
return _subject
.Where(o => o is TEvent)
.Select(o => (TEvent)o)
.ObserveOn(_scheduler);
}
public void Publish<TEvent>(TEvent sampleEvent)
{
_subject.OnNext(sampleEvent);
}
}
It uses an EventLoopScheduler to ensure that all events occur in order and on the same background thread.
Remove the ObserveOn from your subscription because if you observe on another thread you risk having events occur in the wrong order again.
Does this solve your problem?
Try the Synchronize method like:
_publisher.GetEvent<DataEvent>()
.Where(sde => sde.SourceName == source.Name)
.ObserveOn(Scheduler.TaskPool).Synchronize()
.Subscribe(module.OnDataEvent);
Although I tried your scenario with same code and found that the data arrive in sequence and doesn't overlap. May be this is something specific to your application.