How to avoid the use of Subjects in RX - c#

So I keep reading everywhere that use of Subject<T> is "bad" - and I kind of agree with the reasoning.
However, I am trying to think of the best way to avoid using it and have an example.
Currently I have an abstract class for my persisted configuration classes that has a protected Save() method on it which is called whenever changing a property should persist the class. This message pumps a message onto a Subject<T> which is exposed through IObservable<T> interface which the serialisation services listens to and serialises the class. This seemed the most obvious, simple and quickest way to implement this at the time.
So what would be the RX way to do this without using a Subject? Would I instead expose an event and use Observable.FromEventPattern() to subscribe to it? - as this seems a more complex way to go about it.

It's not so much that the use of Subject<T> is bad - there has to be some way of "entering the monad" - that's the academic way of saying "get an IObservable<T>". You need to start somewhere.
The problem with Subject<T> arises more when it's used from a subscription instead of chaining existing observables together. Subjects should just exist at the edges of your Rx machinery.
If none of the provided entry points (e.g. FromEvent, FromEventPattern, FromAsync, Return, ToObservable() and so on) work for you then using Subject<T> is perfectly valid. And there's no need to add extra complexity just to facilitate using one of the above - most of them use subjects or subject-like constructs under the covers anyway.
In your case, sounds like Subject<T> is just fine. You might what to look at exposing it via AsObservable() in order to hide the implementation details.

A simple way to enter the observable is via an Action
private Action<ObservableArgs> _action;
Create the observable
public IObservable<ObservableArgs> GetObservable()
{
return Observable.FromEvent<ObservableArgs>>(
ev => _action += ev,
ev => _action -= ev);
}
Then add to the observable using
public void OnNext(ObservableArgs args)
{
_action?.Invoke(args);
}

Related

How to use Caliburn Micro's EventAggregator to send empty events (no payload)?

I found articles about and solutions to this question pertaining to Prism, but I didn't find anything pertaining to Caliburn Micro. I checked all questions here tagged with Caliburn.Micro and EventAggregator, but didn't find anything Caliburn specific about this seemingly basic issue.
Scenario: I want to publish events to the EventAggregator that don't have any information, other than signaling that something happened.
Problem: First, in Caliburn Micro, the EventAggregator's Publish() method requires an instance of a type to be sent. Second, subscribing and handling events require the implementation of the IHandle<T> interface, where T is the type of instances that we want to receive. It seems that this is fully designed around publishing and handling actual data.
Goal: To be able to publish simple events without having to create and instantiate multiple empty/dummy classes, and without having to Handle() unnecessary events that I need to filter further with conditionals.
My solution so far
This is what I want to improve/replace. (Obviously, this solution is problematic because it creates tighter coupling around the concrete classes, but in my use case this is not a big issue, since it's a small project with singular publishing components for a given event, and the EventAggregator serves other practical goals.)
I made a generic Signal<T> class that implements the singleton pattern, providing a static instance of itself through the Instance property:
public class Signal<T>
{
public static readonly Signal<T> Instance = new Signal<T>();
private Signal() { }
}
So I can publish events in the following way (SignalSourceClass is an example):
_eventAggregator.PublishOnUIThread(Signal<SignalSourceClass>.Instance);
And handle events by declaring the implementation of IHandle<T> in the following way:
IHandle<Signal<SignalSourceClass>>
This way I can send and receive "empty" events by creating only this single Signal class. (Of course this is a limited solution, since components can only send one event this way.)
I suspect that this solution is primitive (well, let's just call it a fact), and that there is something better that I'm overlooking.
Just create a enum with all possible signals you want:
public enum ProjectSignals
{
Connected,
Disconnected,
Openned
}
then just
_eventAggregator.PublishOnUIThread( ProjectSignals.Connected );
and
class SomeClass : IHandle<ProjectSignals>
{
public void Handle( ProjectSignals signal )
{
switch (signal)
{
case Connected:
break;
}
}
}

Best practice for interface to allow adding, deleting etc. child objects w/ broadcasting events (similar to ObservableCollection)

I'm trying to specify an interface for a Folder. That interface should allow to
- Add or delete files of type IFile
- Get an List of IFile
- Broadcast events whenever a file was added/deleted/changed (e.g. for the GUI to subscribe to)
and I'm trying to find the best way to do it. So far, I came up with three ideas:
1
public interface IFolder_v1
{
ObservableCollection<IFile> files;
}
2
public interface IFolder_v2
{
void add(IFile);
void remove(IFile);
IEnumerable<IFile> files { get; }
EventHandler OnFileAdded { get; }
EventHandler OnFileRemoved { get; }
EventHandler OnFileDeleted { get; }
}
3
public interface IFolder_v3
{
void add(IFile);
void remove(IFile);
IEnumerable<IFile> files { get; }
EventHandler<CRUD_EventArgs> OnFilesChanged { get; }
}
public class CRUD_EventArgs : EventArgs
{
public enum Operations
{
added,
removed,
updated
}
private Operations _op;
public CRUD_EventArgs(Operations operation)
{
this._op = operation;
}
public Operations operation
{
get
{
return this._op;
}
}
}
Idea #1 seems really nice to implement as doesn't require much code, but has some problems: What, for example, if an implementation of IFolder only allows to add files of specific types (Say, text files), and throws an exception whenever another file is being added? I don't think that would be feasible with a simple ObservableCollection.
Idea #2 seems ok, but requires more code. Also, defining three separate events seems a bit tedious - what if an object needs to subscribe to all events? We'd need to subscribe to 3 different eventhandlers for that. Seems annoying.
Also a little less easy to use than solution #1 as now, one needs to call .Add to add files, but a list of files is stored in .files etc. - so the naming conventions are a bit less clear than having everything bundled up in one simple sub-object (.files from idea #1).
Idea #3 circumvents all of those problems, but has the longest code. Also, I have to use a custom EventArgs class, which I can't imagine is particularly clean in an interface definition? (Also seems overkill to define a class like that for simple CRUD event notifications, shouldn't there be an existing class of some sort?)
Would appreciate some feedback on what you think is the best solution (possibly even something I haven't thought of at all). Is there any best practice?
Take a look at the Framework's FileSystemWatcher class. It does pretty much what you need, but if anyway you still need to implement your own class, you can take ideas by looking at how it is implemented (which is by the way similar to your #2 approach).
Having said that, I personally think that #3 is also a very valid approach. Don't be afraid of writing long code (within reasonable limits of course) if the result is more readable and maintainable than it would be with shorter code.
Personally I would go with #2.
In #1 you just expose a entire collection of objects, allowing everyone to do anything with them.
#3 seems less self explanatory to me. Though - I like to keep thing simple when coding so I may be biased.
If watchers are going to be shorter-lived than the thing being watched, I would avoid events. The pattern exemplified by ObservableCollection, where the collection gives a subscribed observer an IDisposable object which can be used to unsubscribe is a much better approach. If you use such a pattern, you can have your class hold a weak reference (probably use a "long" weak reference) to the the subscription object, which would in turn hold a strong reference (probably a delegate) to the subscriber and to the weak reference which identifies it. Abandoned subscriptions will thus get cleaned up by the garbage collector; it will be the duty of a subscriber to ensure that a strongly-rooted reference exists to the subscription object.
Beyond the fact that abandoned subscriptions can get cleaned up, another advantage of using the
"disposable subscription-object" approach is that unsubscription can easily be made lock-free and thread-safe, and run in constant time. To dispose a subscription, simply null out the delegate contained therein. If each attempt to add a subscription causes the subscription manager to inspect a couple of subscriptions to ensure that they are still valid, the total number of subscriptions in existence will never grow to more than twice the number that were valid as of the last garbage collection.

Push new values after creation

Reading IntroToRx website, it discourages using of Subject in favour of Observable.Create helper method.
As I can see, the OnNext method can be called only into subscribe method, because it's the only part I have access Observer object.
What if I would like to push new values after it's creation?
Am I "forced" to use a Subject?
If you are just exploring Rx, go for it - use Subjects, go nuts, see how they work, discover their pros and cons for yourself, then come back here and read the questions discussing why Subject is frowned upon.
Subjects offer a much easier way of "quickly bootstrapping" ideas and complicated Rx scenarios without needing to replicate the actual source conditions.
That said, they do inject state into what is kinda-sorta-supposed-to-be a stateless chain of operations, so be careful not to rely on them.
So, to sum up: if you are trying to generate sequences to test/learn how rx works or how you might make query X, use those subjects. If you find yourself using them intra-query, there is a CHANCE there is a better way.
Edit: realized I missed something:
Also, you ask if there is another way of raising stream events post-creation...the answer is yes; you might declare a stream via Create or Return or Generate that returns any old IObservable-based object that you define, which can also expose methods to inject events...or heck, have a lambda that spins a thread that checks a shared list that is routed to the return stream....I guess what I'm saying is that the possibilities are endless. There are something like a dozen "create a sequence of events" methods declared on Observable - try them all!
EDIT 2:
An example? Sure, let's throw something together using Observable.Create that mimics a really inefficient Subject:
var running = true;
var values = new ConcurrentQueue<int>();
var query = Observable.Create<int>(obs =>
{
var body = Task.Factory.StartNew(()=>
{
while(running)
{
int nextValue;
if(values.TryDequeue(out nextValue))
{
obs.OnNext(nextValue);
}
Thread.Yield();
}
});
return Disposable.Create(() =>
{
try
{
running = false;
body.Wait();
obs.OnCompleted();
}
catch(Exception ex)
{
obs.OnError(ex);
}
});
});
using(query.Subscribe(Console.WriteLine))
{
values.Enqueue(1);
values.Enqueue(2);
values.Enqueue(3);
values.Enqueue(4);
Console.ReadLine();
}
Note that this is just quick-and-extremely-dirty example code. :)
It depends on what you are trying to do. There are cases for Subjects, but just not as many as one thinks when they first start out with Rx.
How will the new data enter your sequence? Will it be from another event? Perhaps a message from a communications framework? Maybe polling a file?
Depending on these answers you will normally find that you already have some sort of event source, and you are just converting to Rx from another pattern (Events, Polling, Callbacks etc...)
You also don't just have to use Observable.Create. You could use Observable.Timer/Interval to set up a polling sequence, Observable.FromEventPattern to leverage an existing Event, Observable.Start for a one off async task style calculation etc...
As Rx (or even Linq) can be quite abstract, asking abstract questions can often lead to very broad answers. If you give an indication of a problem you are trying to solve, that might help provide you with an even better answer.
If you are receiving data from external device, you have no intention of signaling errors with IObserver.OnError (you assume your stream is endless and/or any problems with communications are within message itself), you poll at some rate, the only problem with Subject is that you will probably start polling this device even before anyone subscribes (but added benefit is that handling your state is pretty obvious, you created one object, it opened COM port, it communicates and publishes values)
Using Observable.Create or Observable.Timer/Interval might be better - but laziness is main reason, you will manage state anyway. And you will probably need to use Publish().RefCount() to prevent second subscription from opening port.

How to best structure this API to store generic delegates for later execution

I have a custom MVC framework in which I'm overhauling the routing API. I'm trying to think of a clean way to segregate "setup" and "execution" in my framework which makes extensive use of delegates and generics. Right now I envision this from the calling side:
//setup
MyRouter.AddRoute("/foo", () => new MyHandler(), (h) => h.MyMethod);
//h.MyMethod only exists in MyHandler, not in HttpHandler
//execution
MyRouter.Execute(HttpContext);
I can make the AddRoute method signature "work" currently:
delegate T HandlerInvoker<T>();
delegate string HandlerCallMethod<T>(T handler);
...
public void AddRoute<T>(string pattern, HandlerInvoker<T> invoker, HandlerCallMethod<T> caller) where T is HttpHandler{...}
If I didn't need to store the invoker and caller and could do it all right then, this would work fine. But, I do need to store the invoker and caller to later execute.
Current things I've thought about doing:
Storing them in a List<object> and then using reflection to call them. This seems extremely complicated and probably not too good of performance
Moving AddRoute to execution. This can make it harder for people using my API, but might end up being my only "good" choice
Ask a SO question :)
Is there any good way of storing these generic types without a ton of painful reflection?
You could store an anonymous delegate that performs all the conversion for you.
It looks like the following would work (not tested in any way):
List<Action> handlers;
handlers.Add(() => caller(invoker()));
Note that this wouldn't work if you were caching invoker.
In that case you need to make preserve the value, Lazy should do the trick.
List<Action> handlers;
Lazy<T> lazy = new Lazy<T>(invoker);
handlers.Add(() => caller(lazy.Value);
That latter will only create one instance of the return value of invoker per call to the method. And since lazy is a local variable, it is automatically shoved into a class which is held onto as long as handlers holds onto a reference for you.
Note that I ignored pattern, but it seems you don't need any help there.

C# -Priority based delegates and chaining in delegates possible? or Windows Work Flow?

Whenever i feel hungry i will publish i am hungry.This will be notified to the service providers say (MealsService,FruitService,JuiceService ).(These service providers know what to serve).
But the serving priority is the concern. Priority here means my first choice is MealsService when there are enough meal is available my need is end with MealsService.To verify the enough meal is availabe the MealsService raises the event "updateMeTheStockStatus" to the "MealsServiceStockUpdateListener" .
The "MealsServiceStockUpdateListener" will only reply back to "MealsService" . No other Service providers ( FruitService,JuiceService ) will be notified by the "MealsServiceStockUpdateListener" .If there is no sufficient stock then only the MealsService passes notification to the JuiceService (as it is the second priority).As usual it checks the stock.If stock is not sufficient it passes message to FruitService,so the flow continues like this.
How can i technically implement this?
Any implemention like priority based delagates and delegate chaining make sense ?
(Somebody! Please reframe it for good readability ).
Update : In this model there is no direct communication between "StackUpdateListener" and "me".Only The "Service Providers" will communicate me.
Like other answerers, I'm not entirely convinced that an event is the way forward, but let's go along with it for the moment.
It seems to me that the business with the MealsServiceStockUpdateListener is a red herring really - you're just trying to execute some event handlers but not others. This sort of thing crops up elsewhere when you have a "BeforeXXX" event which allows cancellation, or perhaps some sort of exception handling event.
Basically you need to get at each of your handlers separately. There are two different ways of doing that - either you can use a normal multicast delegate and call GetInvocationList() or you can change your event declaration to explicitly keep a list of handlers:
private List<EventHandler> handlers = new List<EventHandler>();
public event EventHandler MealRequired
{
add { handlers.Add(value); }
remove
{
int index = handlers.LastIndexOf(value);
if (index != -1)
{
handlers.RemoveAt(index);
}
}
}
These two approaches are not quite equivalent - if you subscribe with a delegate instance which is already a compound delegate, GetInvocationList will flatten it but the List approach won't. I'd probably go with GetInvocationList myself.
Now, the second issue is how to detect when the meal has provided. Again, there are two approaches. The first is to use the normal event handler pattern, making the EventArgs subclass in question mutable. This is the approach that HandledEventArgs takes. The second is to break the normal event pattern, and use a delegate that returns a value which can be used to indicate success or failure (and possibly other information). This is the approach that ResolveEventHandler takes. Either way, you execute the delegates in turn until one of them satistfies your requirements. Here's a short example (not using events per se, but using a compound delegate):
using System;
public class Test
{
static void Main(string[] args)
{
Func<bool> x = FirstProvider;
x += SecondProvider;
x += ThirdProvider;
Execute(x);
}
static void Execute(Func<bool> providers)
{
foreach (Func<bool> provider in providers.GetInvocationList())
{
if (provider())
{
Console.WriteLine("Done!");
return;
}
}
Console.WriteLine("No provider succeeded");
}
static bool FirstProvider()
{
Console.WriteLine("First provider returning false");
return false;
}
static bool SecondProvider()
{
Console.WriteLine("Second provider returning true");
return true;
}
static bool ThirdProvider()
{
Console.WriteLine("Third provider returning false");
return false;
}
}
Rather than publish a message "I'm hungry" to the providers, publish "I need to know current stock available". Then listen until you have enough information to make a request to the correct food service for what you need. This way the logic of what-makes-me-full is not spread amongst the food services... It seems cleaner to me.
Message passing isn't baked into .NET directly, you need to implement your own message forwarding by hand. Fortunately, the "chain of responsiblity design pattern" is designed specifically for the problem you're trying to solve, namely forwarding a message down a chain until someone can handle it.
Useful resources:
Chain of Responsibility on Wikipedia
C# implementation on DoFactory.com
I'm not sure if you really need a priority event. Anyways, let's suppose we want to code that just for fun.
The .NET Framework has no support for such a peculiar construct. Let me show one possible approach to implement it.
The first step would be to create custom store for event delegates (like described here);
Internally, the custom event store could work like a priority queue;
The specific EventArgs used would be HandledEventArgs (or a subclass of it). This would allow the event provider to stop calling handlers after one of them sets the event as Handled;
The next step is the hardest. How to say to tell the event provider what is the priority of the event handler that is being added?
Let me clarify the problem. Usually, the adding of a handler is like this:
eater.GotHungry += mealsService.Someone_GotHungry;
eater.GotHungry += juiceService.Someone_GotHungry;
eater.GotHungry += fruitService.Someone_GotHungry;
The += operator will only receive an delegate. It's not possible to pass a second priority parameter. There might be several possible solutions for this problem. One would be to define the priority in a custom attribute set at the event handler method. A scond approach is discussed in the question.
Compared to the chain of responsibility implementation at dofactory.com, this approach has some advantages. First, the handlers (your food services) do not need to know each other. Also, handlers can be added and remove at any time dynamically. Of course, you could implement a variation of a chain of responsibility that has this advantages too.
I don't think delegates are the proper solution to your problem. Delegates are a low-level service provided by C# for relatively tightly coupled events between components. If I understand your question properly (It is worded a little oddly, so I am not sure I clearly understand your problem), then I think what you need is a mediated consumer/provider.
Rather than having your consumers directly consume the meal, juice, and fruit providers, have them request a food item from a central mediator. The mediator would then be responsible for determining what is available and what should be provided to the consumer. The mediator would be a subscriber to events published by all three services. Whenever stock is added/updated in the Meal, Juice, or Fruit services, they would publish their current stock to all subscribers. The mediator, being a subscriber, would track current stock reductions on its own, and be able to determine for itself whether to send a meal, juice, or fruit to a food consumer when a get food request is made.
For example:
|---------- (GetFoodResponse) ----------------
V |
FoodConsumer ---- (GetFoodRequest) ------> FoodProvider <-----> [ Local Stock Data ]
^
|
|
MealService ---- (PublishStockMessage) ----------|
^
JuiceService --- (PublishStockMessage) ----------|
^
FruitService --- (PublishStockMessage) ----------|
The benefits of such a solution are that you reduce coupling, properly segregate responsibility, and solve your problem. For one, your consumers only need to consume a single service...the FoodProvider. The FoodProvider subscribes to publications from the other three services, and is responsible for determining what food to provide to a consumer. The three food services are not responsible for anything related to the hunger of your food consumers, they are only responsible for providing food and tracking the stock of the food they provide. You also gain the ability to distribute the various components. Your consumers, the food provider, and each of the three food services can all be hosted on different physical machines if required.
However, to achieve the above benefits, your solution becomes more complex. You have more parts, and they need to be connected to each other properly. You have to publish and subscribe to messages, which requires some kind of supporting infrastructure (WCF, MSMQ, some third party ESB, custom solution, etc.) You also have duplication of data, since the food provider tracks stock on its own in addition to each of the food services, which could lead to discontinuity in available stock. This can be mitigated if you manage stock updated properly, but that would also increase complexity.
If you can handle the additional complexity, ultimately, a solution like this would more flexible and adaptable than a more tightly connected solution that uses components and C# events in a local-deployment-only scenario (as in your original example.)
I am having a bit of trouble understanding your analogy here, which sounds like you're obscuring the actual intent of the software, but I think I have done something like what you are describing.
In my case the software was telemarketing software and each of the telemarketers had a calling queue. When that queue raises the event signifying that it is nearing empty, the program will grab a list of available people to call, and then pass them through a chain of responsibility which pushes the available call into the telemarketer's queue like so:
Each element in the chain acts as a priority filter: the first link in the chain will grab all of the people who have never been called before, and if it finishes (ie. went through all of the people who have never been called) without filling up the queue, it will pass the remaining list of people to call to the next link in the chain - which will apply another filter/search. This continues until the last link in the chain which just fires off an e-mail to an administrator indicating that there are no available people to be called and a human needs to intervene quickly before the telemarketers have no work to do.

Categories

Resources