Overriding the method and subscribing to the event is the same? - events

class A
{
public event EventHanler MyEvent;
protected virtual void OnMyEvent(EventArgs e)
{
if (MyEvent!=null)
MyEvent(this, e);
}
public void DoEvent()
{
//................
MyEvent(this, new EventArgs());
}
}
class B: A
{
private A a = new A();
public B ()
{
a.MyEvent += MyMethod;
}
public void MyMethod(object sender, EventArgs e)
{
Console.WriteLine("Event handler");
}
}
class C : A
{
private A a = new A();
protected override void OnMyEvent(EventArgs e)
{
base.OnMyEvent(e);
Console.WriteLine("OnMyEvent overriding");
}
}
I subscribe to the event and override the method OnMyEvent() in the classes B and C. Pay attension calling the method base.OnMyEvent(e) is in the beginning of the method C.OnMyEvent(...).
As far as I'm concerned there are no differences here. In other words if I call base.OnMyEvent(e) in the beginning of the overriding method, it would mean the same as I just subscribe to the event?
Are there actually no differences?

There is a difference:
Invoking C.OnMyEvent() raises MyEvent. (Conversely, raising MyEvent will not invoke C.OnMyEvent().)
B.MyMethod handles MyEvent. Thus, raising MyEvent will invoke B.MyMethod. (Conversely, invoking B.MyMethod will not raise MyEvent.)

Related

RxJava cache last item for future subscribers

I have implemented simple RxEventBus which starts emitting events, even if there is no subscribers. I want to cache last emitted event, so that if first/next subscriber subscribes, it receive only one (last) item.
I created test class which describes my problem:
public class RxBus {
ApplicationsRxEventBus applicationsRxEventBus;
public RxBus() {
applicationsRxEventBus = new ApplicationsRxEventBus();
}
public static void main(String[] args) {
RxBus rxBus = new RxBus();
rxBus.start();
}
private void start() {
ExecutorService executorService = Executors.newScheduledThreadPool(2);
Runnable runnable0 = () -> {
while (true) {
long currentTime = System.currentTimeMillis();
System.out.println("emiting: " + currentTime);
applicationsRxEventBus.emit(new ApplicationsEvent(currentTime));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable runnable1 = () -> applicationsRxEventBus
.getBus()
.subscribe(new Subscriber<ApplicationsEvent>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable throwable) {
}
#Override
public void onNext(ApplicationsEvent applicationsEvent) {
System.out.println("runnable 1: " + applicationsEvent.number);
}
});
Runnable runnable2 = () -> applicationsRxEventBus
.getBus()
.subscribe(new Subscriber<ApplicationsEvent>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable throwable) {
}
#Override
public void onNext(ApplicationsEvent applicationsEvent) {
System.out.println("runnable 2: " + applicationsEvent.number);
}
});
executorService.execute(runnable0);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.execute(runnable1);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.execute(runnable2);
}
private class ApplicationsRxEventBus {
private final Subject<ApplicationsEvent, ApplicationsEvent> mRxBus;
private final Observable<ApplicationsEvent> mBusObservable;
public ApplicationsRxEventBus() {
mRxBus = new SerializedSubject<>(BehaviorSubject.<ApplicationsEvent>create());
mBusObservable = mRxBus.cache();
}
public void emit(ApplicationsEvent event) {
mRxBus.onNext(event);
}
public Observable<ApplicationsEvent> getBus() {
return mBusObservable;
}
}
private class ApplicationsEvent {
long number;
public ApplicationsEvent(long number) {
this.number = number;
}
}
}
runnable0 is emitting events even if there is no subscribers. runnable1 subscribes after 3 sec, and receives last item (and this is ok). But runnable2 subscribes after 3 sec after runnable1, and receives all items, which runnable1 received. I only need last item to be received for runnable2. I have tried cache events in RxBus:
private class ApplicationsRxEventBus {
private final Subject<ApplicationsEvent, ApplicationsEvent> mRxBus;
private final Observable<ApplicationsEvent> mBusObservable;
private ApplicationsEvent event;
public ApplicationsRxEventBus() {
mRxBus = new SerializedSubject<>(BehaviorSubject.<ApplicationsEvent>create());
mBusObservable = mRxBus;
}
public void emit(ApplicationsEvent event) {
this.event = event;
mRxBus.onNext(event);
}
public Observable<ApplicationsEvent> getBus() {
return mBusObservable.doOnSubscribe(() -> emit(event));
}
}
But problem is, that when runnable2 subscribes, runnable1 receives event twice:
emiting: 1447183225122
runnable 1: 1447183225122
runnable 1: 1447183225122
runnable 2: 1447183225122
emiting: 1447183225627
runnable 1: 1447183225627
runnable 2: 1447183225627
I am sure, that there is RxJava operator for this. How to achieve this?
Your ApplicationsRxEventBus does extra work by reemitting a stored event whenever one Subscribes in addition to all the cached events.
You only need a single BehaviorSubject + toSerialized as it will hold onto the very last event and re-emit it to Subscribers by itself.
You are using the wrong interface. When you susbscribe to a cold Observable you get all of its events. You need to turn it into hot Observable first. This is done by creating a ConnectableObservable from your Observable using its publish method. Your Observers then call connect to start receiving events.
You can also read more about in the Hot and Cold observables section of the tutorial.

how to make and AsyncCallback deliver data before next method is called

I have a method that calls 2 services that make AsyncCallBacks
centroService.buscarCentroPorNombre(nombreCentroSeleccionado, new AsyncCallback<Centro>() {
#Override
public void onSuccess(Centro centro) {
cArticuloCentro.setIdCentro(centro.getIdCentro());
cArticuloCentro.setPrecio(Double.parseDouble(precioTextBox.getText()));
}
#Override
public void onFailure(Throwable caught) {
//do something
}
});
articuloService.buscarArticuloPorNombre(nombreArticuloSeleccionado, new AsyncCallback<Articulo>() { //se llama al sevivio para q busque el la base de datos la Entity por nombre
public void onSuccess(Articulo articulo) {
cArticuloCentro.setIdArticulo(articulo.getCod());
}
#Override
public void onFailure(Throwable caught) {
//do something
}
});
the problem comes when the next method is called
becouse these serviceCalls are asynchronous method activates before the calls are made, does not getting desired data. next method is
save(){
articuloCentroService.saveArticuloCentro(cArticuloCentro, new AsyncCallback<String>() {
#Override
public void onFailure(Throwable caught) {
//do something
}
#Override
public void onSuccess(String result) {
Window.alert("saved");
}
});
}
please can you tell me a way to make save() method execute when the asyncCallbacks have finished
thank you
In pure java you would need to synchronize threads, but in GWT, there's only one thread running at all times, so you can do a simply sync logic using an array:
final int[] sync = new int[1];
centroService.buscarCentroPorNombre(nombreCentroSeleccionado, new AsyncCallback<Centro>() {
#Override
public void onSuccess(Centro centro){
//...
if (++sync[0] == 2){
save();
}
}
#Override
public void onFailure(Throwable caught) {
//do something
}
});
articuloService.buscarArticuloPorNombre(nombreArticuloSeleccionado, new AsyncCallback<Articulo>() {
public void onSuccess(Articulo articulo) {
//...
if (++sync[0] == 2){
save();
}
}
#Override
public void onFailure(Throwable caught) {
//do something
}
});
Explanation: since there's only one thread running, the sync array will only be updated by one thread at a time. You can't control which method will finish first, but when they do, only one callback will be executed at a time. The sync array is just a counter you can use to sync any number of async invocations.

Register to C# event from C++/CLI

I'm writing C++ code that calls C# code. The C# may need to invoke methods back in the C++ code. If both parts were C# I think I would use following mechanism. Please note I pass EventHandler from ShouldBCpp to Csharp instead of registering in ShouldBCpp since ShouldBCpp does not know what csharp points to (& can't change CsharpBase).
public abstract class CsharpBase
{
public abstract void SomeMethodDoingActionInB();
}
public class Csharp : CsharpBase
{
public Csharp(EventHandler f)
{
MySpecialHook += f;
}
public event EventHandler MySpecialHook;
public override void SomeMethodDoingActionInB()
{
if (MySpecialHook != null)
MySpecialHook(this, null);
}
}
public class ShouldBCpp
{
public CsharpBase csharp;
public ShouldBCpp()
{
csharp = new Csharp(NotificationFromClassB); // actually using Activator::CreateInstance
}
public void NotificationFromClassB(object sender, EventArgs e)
{
}
public void Go()
{
csharp.SomeMethodDoingActionInB();
}
}
class Program
{
static void Main(string[] args)
{
ShouldBCpp shouldBCpp = new ShouldBCpp();
shouldBCpp.Go();
}
}
Question is how to write ShouldBCpp in C++/CLI. Bonus points for using delegate :)
Thank you
A simple translation to C++/CLI would look like this:
public ref class IsCppCLI
{
public:
CsharpBase^ csharp;
IsCppCLI()
{
csharp = gcnew Csharp(gcnew EventHandler(this, &IsCppCLI::NotificationFromClassB));
// You didn't show your Activator code,
// but I believe it would translate to C++/CLI as this:
csharp = dynamic_cast<CsharpBase^>(
Activator::CreateInstance(
Csharp::typeid,
gcnew array<Object^> {
gcnew EventHandler(this, &IsCppCLI::NotificationFromClassB)}));
}
void NotificationFromClassB(Object^ sender, EventArgs^ e)
{
}
void Go()
{
csharp->SomeMethodDoingActionInB();
}
}

raising events in chaining classes

say I have three classes: class1, control1 and form1; form1 instantiate contorl. and control1 instantiate class1, the later produces some event that I need to 'bypass' to form1, to achieve that I have made an intermediate function as shown below:
public delegate void TestHandler(String^ str);
public ref Class class1
{
event TestHandler^ TestHappen;
void someFunction()
{
TestHappen("test string");
}
};
public ref Class control1
{
event TestHandler^ TestHappen;
class1^ class1Obj;
control1()
{
class1Obj= gcnew class1();
class1Obj->TestHappen+= gcnew TestHandler(this,&control1::onTest);
}
void onTest(String^ str)
{
TestHappen(str);
}
};
public ref Class form1
{
control1^ control1Obj;
form1()
{
control1Obj= gcenw control1();
control1Obj->TestHappen+= gcnew TestHandler(this,&form1::onTest);
}
void onTest(String^ str)
{
//do something with the string...
}
};
I don't want to use class1 in form1, are there a way to remove the intermediate onTest() function.
Yes, if you use a custom event, you can write its add-handler and remove-handler functions so that they add and remove the delegate directly from another object's event.
For example:
public ref class control1 // in "ref class", class is lowercase!
{
class1 class1Obj; // stack-semantics syntax, locks class1Obj lifetime to be same as the containing control1 instance
public:
event TestHandler^ TestHappen {
void add(TestHandler^ handler) { class1Obj.TestHappen += handler; }
void remove(TestHandler^ handler) { class1Obj.TestHappen -= handler; }
}
};

Contravariance problems with event properties

Suppose I have a simple EventArgs subclass:
class MyArgs : EventArgs { }
Consider I have two classes with events:
class MyData {
public event EventHandler<MyArgs> Method;
}
class MyObject {
public event EventHandler Method;
}
And a simple program that uses them:
static void Main(string[] args){
MyObject o = new MyObject();
o.Method += MyMethod;
MyData data = new MyData();
data.Method += MyMethod;
}
static void MyMethod(object sender, EventArgs e) { }
Thanks to Contravariance, MyMethod counts as both an EventHandler and an EventHandler<MyArgs>. However, if I change MyObject's event handler into a property that forwards the method to a MyData:
class MyObject {
MyData data = new MyData();
public event EventHandler Method {
add { data.Method += value; }
remove { data.Method += value; }
}
}
The event property is unable to forward the EventHandler to the EventHandler. This seems strange to me because it seems to fall into the contravariance category - a handler with a weaker signature (base classes) should be able to accept arguments with a stronger signature (subclasses).
Why won't C# let me do this? Is there a way to tunnel a generic EventHandler down through an event property into an EventHandler? Is there some sort of legal cast that can be performed on the delegates?
There is no implicit conversion from EventHandler to EventHandler<T>. However since both are of compatible types with each other, you could just pass the EventHandler to the constructor to "convert" it.
public event EventHandler Method
{
add { data.Method += new EventHandler<MyArgs>(value); }
remove { data.Method -= new EventHandler<MyArgs>(value); }
}

Resources