I am struggling to find the standard implementation for a very basic observer that late binds and hosts other observers in it.
public class CompoundObserver<T> : IObserver<T>
{
public readonly List<IObserver<T>> observers;
public CompoundObserver()
{
this.observers = new List<IObserver<T>>();
}
public void Register(IObserver<T> observer)
{
this.observers.Add(observer);
}
public void OnCompleted()
{
this.observers.ForEach(observer =>
{
observer.OnCompleted();
});
}
public void OnError(Exception error)
{
this.observers.ForEach(observer =>
{
observer.OnError(error);
});
}
public void OnNext(T value)
{
this.observers.ForEach(observer =>
{
observer.OnNext(value);
});
}
}
What is the standard mechanism for something like this in RX .NET?
Related
I have a number of methods that are called on different 3rd party systems. I now have another 3rd party system that will have the same set of methods actioned against it. If both 3rd party systems are connected I will then call the methods on each object in turn.
Currently I have a class that I pass round that I can call the method once and it checks and then calls it on each system that is enabled, this has an instance of each objects classes, similar to this:
public class AACSCaller
{
3rdPartySystem1 _system1;
3rdPartySystem2 _system2;
public AACSCaller(Settings appSettings)
{
_appSettings = appSettings;
if (appSettings.system1Enabled)
{
_system1 = new 3rdPartySystem1();
}
if (appSettings.system2Enabled)
{
_system2 = new 3rdPartySystem2();
}
}
public void Method1()
{
if (appSettings.system1Enabled)
{
_system1.Method1();
}
if (appSettings.system2Enabled)
{
_system2.Method1();
}
}
public void Method2()
{
if (appSettings.system1Enabled)
{
_system1.Method2();
}
if (appSettings.system2Enabled)
{
_system2.Method2();
}
}
}
Is this sensible, as it does seem there maybe a better way and I may well be connecting additional system at some point.
A possible solution here is to define an interface or base class for 3rdPartySystem1 and 3rdPartySystem2 classes, store instances in a collection and call required methods for every item in collection. If only one system is enabled, you'll have only one item in collection, if both is enabled, you'll call them one by one in loop
public interface IThirdPartySystem
{
void Method1();
void Method2();
}
public class ThirdPartySystem1 : IThirdPartySystem
{
//implementation
}
public class ThirdPartySystem2 : IThirdPartySystem
{
//implementation
}
public class AACSCaller
{
IList<IThirdPartySystem> _systems = new List<IThirdPartySystem>();
public AACSCaller(Settings appSettings)
{
_appSettings = appSettings;
if (appSettings.system1Enabled)
{
_systems.Add(new ThirdPartySystem1());
}
if (appSettings.system2Enabled)
{
_systems.Add(new ThirdPartySystem2());
}
}
public void Method1()
{
foreach (var system in _systems)
system.Method1();
}
public void Method2()
{
foreach (var system in _systems)
system.Method2();
}
}
I suggest you to use interface that have Method1 and Method2 methods and then create to classes System1 and System2 that are implements the interface. Where AACSCaller is create you initialize the correct implementation of the interface and in your methods your just Call to the correct instance method without conditions.
public class AACSCaller
{
IThirdPartySystem ThirdPartySystem;
public AACSCaller(Settings appSettings)
{
_appSettings = appSettings;
ThirdPartySystem = appSettings.system1Enabled ? new ThirdPartySystem1() : new ThirdPartySystem2();
}
public void Method1() => ThirdPartySystem.Method1();
public void Method2() => ThirdPartySystem.Method2();
}
public interface IThirdPartySystem
{
void Method1();
void Method2();
}
public class ThirdPartySystem1 : IThirdPartySystem
{
public void Method1()
{
//code here..
}
public void Method2()
{
//code here..
}
}
public class ThirdPartySystem2 : IThirdPartySystem
{
public void Method1()
{
//code here..
}
public void Method2()
{
//code here..
}
}
I have the following class:
private class MyRunnable : Java.Lang.Object, Java.Lang.IRunnable
{
private MainActivity mainActivity;
public MyRunnable(MainActivity mainActivity)
{
this.mainActivity = mainActivity;
}
public void Run()
{
mainActivity.RunOnUiThread(() =>
{
mainActivity.ShowAlert();
});
}
}
Then I start it in OnCreate method like that:
MyRunnable myRunnable = new MyRunnable(this);
Java.Lang.Thread thread = new Java.Lang.Thread(myRunnable);
thread.Start();
But the class is too tied up with MainActivity and ShowAlert method. If I want to work with another activity and another method for example:
private class MyRunnable : Java.Lang.Object, Java.Lang.IRunnable
{
private (SomeActivity) someActivity;
public MyRunnable((SomeActivity) someActivity)
{
this.someActivity = someActivity;
}
public void Run()
{
someActivity.RunOnUiThread(() =>
{
mainActivity.(SomeOtherMethod)();
});
}
}
I wouldn't be able to. Is there any way to make it more generic? (I'm using Xamarin.Android)
A simple way is to create an Action-based runnable, passing the Action as a parameter to the runnable .actr (you can also pass additional params, etc...)
C# Action in Java Runnable
public class MyRunnable : Java.Lang.Object, Java.Lang.IRunnable
{
readonly WeakReference<Action> actionRef;
public MyRunnable(Action action)
{
actionRef = new WeakReference<Action>(action);
}
public void Run()
{
actionRef.TryGetTarget(out Action action);
action?.Invoke();
}
}
Usage:
var runnable = new MyRunnable(async () =>
{
// Do whatever you need to do, including capturing of local vars, app/activity context, etc.
await Task.Delay(1000);
Toast.MakeText(this, "In runnable", ToastLength.Long).Show();
~~~
});
runnable.Run();
It seems that it would be easy to implement an interface-based approach:
public interface IRunnableActivity
{
void Run();
}
public class MainActivity : Activity, IRunnableActivity
{
...
public void Run()
{
ShowAlert();
}
}
public class SomeOtherActivity : Activity, IRunnableActivity
{
...
public void Run()
{
SomeOtherMethod();
}
}
private class MyRunnable : Java.Lang.Object, Java.Lang.IRunnable
{
private IRunnableActivity activity;
public MyRunnable(IRunnableActivity runnableActivity)
{
activity = runnableActivity;
}
public void Run()
{
runnableActivity.RunOnUiThread(() =>
{
runnableActivity.Run();
});
}
}
I'll leave you the exercise of deciding how best to get RunOnUiThread with this approach.
You need to decouple ShowAler from MainActivity, create a Utils class, and add the method:
class Utils
{
public static void ShowAlert()
{
Android.Util.Log.Error("lv", "=======");
}
}
In your MyRunnable class, use the base class Activity to achieve polymorphism
public class MyRunnable : Java.Lang.Object, Java.Lang.IRunnable
{
Activity mActivity;
public MyRunnable(Activity activity)
{
mActivity = activity;
}
public void Run()
{
mActivity.RunOnUiThread(() =>
{
Utils.ShowAlert();
}
);
}
}
And then you can use the under code in any Activities:
Thread thread = new Thread(new MyRunnable(this));
thread.Start();
We are using factory to create an instance of Subscribers. Each subscriber can have its own dependency.
Each subscriber will use constructor injection.
Should I pass dependency into subscribers through Subscriber Factory? Every time adding new dependency in any subscriber will change Subscriber factory?
public interface IMessageSubscriber
{
bool Process(string message)
}
public class MessageSubscriber1 : IMessageSubscriber
{
public bool Process(string message)
{
//Some custom logic
}
}
public class MessageSubscriber2 : IMessageSubscriber
{
public bool Process(string message)
{
//Some custom logic
}
}
public class MessageSubscriberFactory
{
//SubscriberType is enum
public IMessageSubscriber Get(SubscriberType type)
{
if(type == 1)
{
return new MessageSubscriber1();
}
else if(type == 2)
{
return new MessageSubscriber2();
}
}
}
//Main class
public class Process
{
public static void Main(string[] args)
{
MessageSubscriberFactory fac = new MessageSubscriberFactory();
foreach SubscriberType
{
string = "Message";
IMessageSubscriber subscriber = fac.Get(type);
subscriber.Process(message)
}
}
}
One approach would be to use named registrations with a DI/IOC container. This would involve using the container in a service locator fashion (which some people oppose), but I think it could make sense in this case. The example below is pretty crude, but it does give you an approach to handle subscribers with different dependencies without passing them into the factory. I used Unity here and you'd want to wrap the container reference rather than referencing directly, but this gets the point across.
public interface ILowerCaseWriter
{
void Write(string message);
}
public class LowerCaseWriter : ILowerCaseWriter
{
public void Write(string message)
{
Console.WriteLine(message.ToLower());
}
}
public interface IUpperCaseWriter
{
void Write(string message, int number);
}
public class UpperCaseWriter : IUpperCaseWriter
{
public void Write(string message, int number)
{
Console.WriteLine("{0}:{1}", number, message.ToUpper());
}
}
public interface ISubscriber
{
void Write();
}
public class Subscriber1 : ISubscriber
{
private ILowerCaseWriter _writer;
public Subscriber1(ILowerCaseWriter writer)
{
_writer = writer;
}
public void Write()
{
_writer.Write("Using subscriber 1");
}
}
public class Subscriber2 : ISubscriber
{
private IUpperCaseWriter _writer;
public Subscriber2(IUpperCaseWriter writer)
{
_writer = writer;
}
public void Write()
{
_writer.Write("Using subscriber 2", 2);
}
}
public class SubscriberFactory
{
private UnityContainer _container;
public SubscriberFactory()
{
_container = new UnityContainer();
_container.RegisterType<ILowerCaseWriter, LowerCaseWriter>();
_container.RegisterType<IUpperCaseWriter, UpperCaseWriter>();
_container.RegisterType<ISubscriber, Subscriber1>("Subscriber1");
_container.RegisterType<ISubscriber, Subscriber2>("Subscriber2");
}
public ISubscriber GetSubscriber(int type)
{
switch (type)
{
case 1:
return _container.Resolve<ISubscriber>("Subscriber1");
case 2:
return _container.Resolve<ISubscriber>("Subscriber2");
default:
throw new Exception();
}
}
}
class Program
{
private static void Main(string[] args)
{
var factory = new SubscriberFactory();
var subscriber = factory.GetSubscriber(1);
subscriber.Write();
Console.ReadLine();
}
}
Hi guys I have a ExternalDataService that is constantly firing real time data, it is contained in a lib.
I have a wrapper class that subscribes and puts the updates on a Observable..
public class MyService
{
private ExternalDataService _externalDataService;
public MyService()
{
_externalDataService= new ExternalDataService ();
}
public IObservable<double> GetData()
{
return Observable.Create<double>(i =>
{
_externalPriceService.OnDataChanged += (s, e) => { i.OnNext(e); };
return () =>
{
// what do I do here?
};
});
}
}
Consumed as...
var p = new MyService();
var disposable = p.GetData().Subscribe(i => Console.WriteLine(i));
How would I unsubscribe from _externalPriceService.OnDataChanged when the Dispose is called on disposable?
Use Observable.FromEvent or Observable.FromEventPattern, instead of Observable.Create. Then you just Dispose the subscription.
Depending on your EventHandler definition, it would be something like this:
public class ExternalDataService {
public EventHandler<DataChangedEventArgs> OnDataChanged;
}
public class DataChangedEventArgs : EventArgs {
public Double Data {
get; set;
}
}
public class MyService {
private ExternalDataService _externalDataService;
public MyService()
{
_externalDataService= new ExternalDataService ();
}
public IObservable<double> GetData()
{
return Observable.FromEventPattern<DataChangedEventArgs>(eh => _externalDataService.OnDataChanged += eh, eh => _externalDataService.OnDataChanged -= eh)
.Select(e => e.EventArgs.Data);
}
}
You can also do something like this:
public IObservable<double> GetData()
{
Action<object, double> dataHandler = null;
return Observable.Create<double>(i =>
{
dataHandler = (s, e) => { i.OnNext(e); };;
_externalDataService.OnDataChanged += dataHandler;
return Disposable.Create(() =>
{
_externalDataService.OnDataChanged -= dataHandler;
});
});
}
edit: stupid typos
I'm trying out an example of using Domain Events to notify of when something has happened in a system (borrowed from here and here).
I'm really close to getting the code working how I want, however, I've hit a bit of a brick wall. Here is my DomainEvents class:
public static class DomainEvents
{
[ThreadStatic]
private static IList<IEventHandler<IDomainEvent>> Actions;
public static void Register<T>(IEventHandler<T> callback) where T : IDomainEvent
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback); // <---- Problem here, since I can't add callback to the collection.
}
public static void ClearCallbacks()
{
Actions = null;
}
public static void Raise<T>(T args) where T : IDomainEvent
{
if (Actions == null)
{
return;
}
foreach (var action in Actions)
{
if (action is IEventHandler<T>)
{
((IEventHandler<T>)action).Handle(args);
}
}
}
The above won't compile because Actions.Add cannot accept callback since it's a IEventHandler<T> type rather then a IEventHandler<IDomainEvent> type. Here's some more code to clarify.
This is called from my console application:
DomainEvents.Register(new CustomerHasUnpaidDuesEventHandler());
CustomerHasUnpaidDuesEventHandler implements IEventHandler<CustomerHasUnpaidDuesEvent>, where CustomerHasUnpaidDuesEvent implements IDomainEvent.
public class CustomerHasUnpaidDuesEventHandler : IEventHandler<CustomerHasUnpaidDuesEvent>
{
public IEmailSender EmailSender { get; set; }
public void Handle(CustomerHasUnpaidDuesEvent #event)
{
this.EmailSender.SendEmail(#event.Customer.EmailAddress);
}
}
public class CustomerHasUnpaidDuesEvent : IDomainEvent
{
public CustomerHasUnpaidDuesEvent(Customer customer)
{
this.Customer = customer;
}
public Customer Customer { get; set; }
}
This is what I don't get - if CustomerHasUnpaidDuesEvent implements IDomainEvent, then why is the call to Actions.Add failing? How can I resolve this?
EDIT:
To make things clearer, here is entire code for my test app:
class Program
{
static void Main()
{
DomainEvents.Register(new CustomerHasUnpaidDuesEventHandler());
var c = new Customer();
c.EmailAddress = "test#dfsdf.com";
c.CheckUnpaidDues();
}
}
public interface IEventHandler<in T> where T : IDomainEvent
{
void Handle(T args);
}
public interface IEmailSender
{
void SendEmail(string emailAddress);
}
public interface IDomainEvent
{
}
public static class DomainEvents
{
[ThreadStatic]
private static IList<IEventHandler<IDomainEvent>> Actions;
public static void Register<T>(IEventHandler<T> callback) where T: IDomainEvent
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback);
}
public static void ClearCallbacks()
{
Actions = null;
}
public static void Raise<T>(T args) where T : IDomainEvent
{
if (Actions == null)
{
return;
}
foreach (IEventHandler<T> action in Actions)
{
(action).Handle(args);
}
}
}
public class CustomerHasUnpaidDuesEventHandler : IEventHandler<CustomerHasUnpaidDuesEvent>
{
public IEmailSender EmailSender { get; set; }
public void Handle(CustomerHasUnpaidDuesEvent #event)
{
this.EmailSender.SendEmail(#event.Customer.EmailAddress);
}
}
public class CustomerHasUnpaidDuesEvent : IDomainEvent
{
public CustomerHasUnpaidDuesEvent(Customer customer)
{
this.Customer = customer;
}
public Customer Customer { get; set; }
}
public class Customer
{
public string Name { get; set; }
public string EmailAddress { get; set; }
public bool HasUnpaidDues { get; set; }
public void CheckUnpaidDues()
{
HasUnpaidDues = true;
DomainEvents.Raise(new CustomerHasUnpaidDuesEvent(this));
}
}
Cheers.
Jas.
There is no need for your Register method to be generic:
public static void Register(IEventHandler<IDomainEvent> callback)
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback);
}
Edit:
The problem is that in order to have IEventHandler<CustomerHasUnpaidDuesEvent> to be in the list of IEventHandler<IDomainEvent>s, we need T to be a covariant template parameter in IEventHandler<T> (which is declared as IEventHandler<out T>). However in order to allow the function Handle(T arg), we need T to be contravariant. So strictly this way won't work. Imagine: if we really could insert an IEventHandler<CustomerHasUnpaidDuesEvent> into a list of IEventHandler<IDomainEvent>s, than someone might try to call Handle with the argument of some type which derives from IDomainEvent but is not a CustomerHasUnpaidDuesEvent! This should be impossible to do.
The solution is that we don't need the exact type at Register, so we can keep a reference to a generic base interface. The implementation is here: http://ideone.com/9glmQ
Old answer is not valid, kept below for consistency.
Maybe you need to declare IEventHandler to accept T as a covariant type?
interface IEventHandler<in T> where T: IDomainEvent
{
void Handle();
// ...
}
Edit: surely CustomerHasUnpaidDuesEvent is an IDomainEvent, but you need IEventHandler<CustomerHasUnpaidDuesEvent> to be a IEventHandler<IDomainEvent>. This is exactly what covariance does. In order to allow that, your template parameter in IEventhandler must be declared covariant (<in T> instead of just <T>).