architecture for bubbling events through classes hierarchy - c#

I have a simple application that consists of a console application and a class library. The class library does all of the heavy lifting throughout its few-dozen classes. Some of those classes are internal to the class library, and even if public, I'd rather not have the console application completely aware of them.
So I could have something like:
My Program.cs class that is running.
My DoSomething.cs class that is being called by Program.cs.
My DoSomethingInParticular.cs class that is being called by DoSomething.cs
And so on, and so on.
Is there a generally understood way of letting Program.cs be aware of lower changes?
Functionally I'd like to have my console application write out lower level events to the console window, which is where I'm trying to go with this.

A module only knows as much as it knows.
I see 2.1 main paths for you.
1) Make public events in DoSomething that Program can listen to.
Make public events in DoSomethingInParticular that DoSomething can listen to.
When DoSomething receives an event it decides if it is proper for bubbling and transforms it to one event of its own and raises it for Program to receive.
1.1) Put the data carrying structures/classes in the events in another, common, lib. Then when an event is received DoSomething doesn't have to transform it but only decide whether to bubble it or not.
2) Make an event handling lib of its own to handle who receives what.
Without knowing more I would go with 1.1.
HTH

Related

Communication between two plugins in C#

I have two plugins that are running inside a third-party host application. The host application has an event called DocumentOpened that is raised when a document is opened.
Both plugins, Plugin A and Plugin B, are subscribing to this event. However, Plugin A and Plugin B do not know about each other, and they are executed independently.
Plugin A)
Host.DocumentOpened += SomeCodeA()
Plugin B)
Host.DocumentOpened += SomeCodeB()
What I want to achieve is to give control back to Plugin A after Plugin B has finished handling the DocumentOpened event. In other words, I want to call a method in Plugin A after Plugin B has finished executing.
To do this to do this you will probably need some way for Plugin A and B to communicate with each other. Here are some methods, but there is probably others:
EventWaitHandle
One fairly simple way would be with a system wide synchronization event. Both plugins would each create a EventWaitHandle with the same name. Plugin A could then create a thread that waits on the event, and Plugin B would set the event. If Plugin B does not exist then the event would never be raised. This is a system wide event, so would not work if multiple instances of the host is running, unless you do something like including the processor-id to the event name.
IPC/RPC methods
There are various ways for processes to communicate with each other that could be used:
Named pipes
Message buss
web service
Windows communication foundation
This would be a more complicated solution, but would also be more generic. It could for example handle if the host application decides to run plugins in separate processes, or if you want to transfer more data between the plugins.
Shared assembly
You could create an assembly that is used by both of your plugins. This would allow you to create a singleton object that is shared between both plugins. Something like this:
public class PluginCommunication
{
public event EventHandler MyEvent;
public void RaiseEvent() => MyEvent?.Invoke(this, EventArgs.Empty);
public static PluginCommunication PluginBEvent = new PluginCommunication();
}
plugin B would call PluginCommunication.PluginBEvent.RaiseEvent(); and plugin A would attach an event handler like PluginCommunication.PluginBEvent.MyEvent += PluginAEventHandler;
There are potential pitfalls with this method. if you need to change the assembly in any way you face the risk of plugin A using version 1 and plugin B using version 2, and that may end badly if you are not very careful. Threading issues might also occur if you do not do everything on the main thread.

Avoiding captive dependencies when using delegates and events with an IOC Container

Say I have a console application or Windows service, and am using dependency injection with an IOC container (in my specific case, I'm using Autofac).
One of the classes that my IOC container resolves is a WorkDoer class, which has a long running DoWork(Args args) method. When DoWork(Args args) completes, a custom event is raised (WorkDone). In my case, DoWork is triggered as messages with parameters are taken off of a message queue.
I also have a Notifier class that I'd like to have subscribe to my WorkDone event.
Concretely
public class Notifier
{
public void Subscribe(WorkDoer w)
{
w.WorkDone += new WorkDoer.WorkDoneHandler(Notify);
}
private void Notify(WorkDoer w, EventArgs e)
{
//do some kind of notification decoupled from my WorkDoer
//concretely I'd like to push a SignalR message or something.
}
}
So now I have my WorkDoer which is responsible for running some long running business logic and raises an event. Then I in theory have my Notifier that can listen for that event and run some logic decoupled from my business logic, such as pushing a notification to an MVC page in that solution, or maybe publishes another message queue message, or something like that.
The projects in my solution are
App.WorkerService -- this contains my WorkDoer console app and my DependencyConfig
App.BusinessLogic -- this is a library that contains all of the business logic that WorkDoer uses
App.Notification -- this is where I'd like my Notifier(s) to live
So here's my problem:
In my WorkerService Program.cs, I have my WorkDoer registered with Autofac's Single Instance Scope. This means that it's a transient instance and can disappear. As such, I'm not sure how I can subscribe to it's WorkDone event effectively in my Program.cs's Main method, since it will eventually get disposed of. I could make it use a singleton scope to avoid this, but then I've captured all of WorkDoer's dependencies within that long running scope, which I don't want to do.
I have my Notifier in a singleton scope so that I don't lose existing subscriptions -- I'm not sure if that's bad practice or not, and I'm happy to change it.
Basically, the big picture is that I want to have my business logic in a separate project than my notification logic to avoid leaking notification code into my business logic. I'd also like to have the ability to easily add/remove/change notifier types (SignalR, log file, MQ, etc.). I'd like to use the C# event and delegate system for this (seems reasonably relevant here), but I'm not sure how to manage my dependency scopes.
I did see this question but I'd like to avoid the suggestions of OnActivated or the delegate registration because of the aforementioned captured dependency concerns.
Currently, you are using an observer design pattern for your notifications. You register the event handlers directly. That results in a tight coupling of the components.
For your requirements above, the publish/subscribe design pattern, using an event aggregator, would be better. The publisher and subscriber are only loosely coupled. Both know only the event aggregator. The event aggregator is injected into both and works as a mediator/facade/adapter.
There are many possible implementations. See:
https://www.codeproject.com/Articles/812461/Event-Aggregator-Pattern
https://www.martinfowler.com/eaaDev/EventAggregator.html
https://www.c-sharpcorner.com/UploadFile/pranayamr/publisher-or-subscriber-pattern-with-event-or-delegate-and-e/

Can I Add a handler to AppDomain.CurrentDomain.UnhandledException in a class library

I want to subscribe to the AppDomain.CurrentDomain.UnhandledException event to catch any errors as im trying a new design pattern where I dont want to put a try catch on every event.
usually in a win forms app there is a main entry point, but this is a class library that is called by another application.
Is there a main entry point in a class library where I can hook up this event, or is it just not possible in a class library unless im sure one method will get called before anything else?
No, class libraries don't have a main entry point. If you feel like you need one, then you could conceptually create one virtually via your public API surface area. In other words, limit what objects are public and in those public objects make sure the call gets made at some point. That could be taken to the extreme of requiring a factory call of some kind to setup your library before doing anything.
// Set the unhandled exception mode to force errors to go through our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// Add the event handler for handling thread exceptions to the event.
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Thanks to Brian Dishaw
Clearly this does not give you some non declarative way of assigning the handler, ala assingning a trace listener in app.config but, that gives me an idea.
You could write your own configuration section that would perform this code. Then when the config is loaded you could assign the event handler, I'll find some links on how to do that ...
However, your configuration would have to be present in the main app so perhaps this is not right.
EDIT Sorry, I don't think there is way to do this without a IoC framework of some kind, what else would load your class. The only options I can think of all require some sort of change to the main application.
I'm interested in being wrong.

What ways can I send data from a plugin across an app domain that triggers an event in the main application in C#?

I have a main application that loads up some plugins. These plugins are loaded and run in separate app domains using a class that inherits from "MarshalByRefObject"; This all works fine.
What I need now is a way to handle when the plugin wants the main app to do something and a way to dynamically handle this in the main application. If the best way is to poll the plugin for a list of commands, then I can do that, although it seems a bit of a kludge.
What are the best ways to send a request from the plugin across the app domain to the main app?
UPDATE
As an update to the question, I am looking to sent data across the app domain that makes the main app do something, like a "File->New" operation or "GetSomeData()" call. In doing this I need to make the Plugin wait for the main app to complete whatever it is doing, but also be able to decide, main app side, whether or not to execute the requested function/event.
I was doing this by passing the plugin an interface. This interface was implemented by a class in the main app that defined some events. The main app could then subscribe to these events and the plugin could make the main app functions fire. The problem is that the interface only referenced the class as it was when I passed the interface. I.e if I created the class with no events subscribed, then passed the interface like this:
CallbackClass myCallbackClass = new CallbackClass();
pluginInterface.HeresMyCallbackClass((ICallbackClass)myCallbackClass);
the plugin would receive the interface, but any changes to the original class did not propagate. So adding:
myCallbackClass.MyMainAppEvent += new MainEventHandler(MyMainAppFunction);
would not change the plugin's version of the event. The plugin could do this:
//code within plugin
ICallbackClass callToMainApp;
public HeresMyCallbackClass(ICallbackClass cbClass)
{
callToMainApp = cbClass;
}
public CallAMainAppFunction()
{
callToMainApp.CallTheSubscribedFunction(); //This is where it all goes wrong
}
...but the event that it tries to call is null. Now, this is not a problem if I make the main app subscribe to the event first, then pass the interface:
CallbackClass myCallbackClass = new CallbackClass();
myCallbackClass.MyMainAppEvent += new MainEventHandler(MyMainAppFunction); //Subscribe first
pluginInterface.HeresMyCallbackClass((ICallbackClass)myCallbackClass);
The plugin could then call CallTheSubscribedFunction() and the event would fire in the main app. I need to be able to subscribe to events like this on demand because some things/events/data in the main app are available at different times.
So, a lot of info I was trying to avoid having to write out, but I guess my question was too general in relation to my issue.
If anyone has suggestions please let me know. Again, my goal is to allow the plugin to trigger an event in the main app, wait for the main app to finish, then continue with it's execution, where the main app may or may not be subscribed to the events.
Update 2
I realize the above info is specialized to my application, but I'm looking for general suggestions as well. So, if using threads is an option, let me know how a general case might work. If another case would work better and I need to do some redesigning to implement it let me know that as well. Just looking for suggestions here. Thanks.
Mike from the looks of it, you're sort of already what what I think is required and that you should use the Observer Pattern between the class in your primary app domain and the secondary app domain.
You probably just need to iron out the some rough edges in the code you've got, in word words follow/implement the observer pattern.
The way it would work is that the class in the primary domain subscribes to "events" that the class that's been loaded in the secondary app domain raises. I'm guessing that you'll need to do this at the time the secondary app domain classes is instantiated. If you're unloading the app domain, then also make sure of "subscriptions" are "disconnected".
Does that make sense?
Make sure that your CallbackClass inherits from MarshalByRefObject. Otherwise, a copy of the callback class will be created on the other side of the appdomain boundary, making cross-appdomain communication impossible.

DoEvents In a DLL

Do you have any ideas how to call DoEvents from a C# DLL
Don't. It's sketchy enough when you are the app controlling the event loop; pumping messages from a DLL just adds to the risk that you'll end up hitting code a naive programmer didn't make safe for re-entrancy.
Do you mean System.Windows.Forms.Application.DoEvents()?
I'd echo the "don't" (either from a dll or a UI project). There are several things you can do to make library code play nicely with a UI,including the same threading tricks (with events and/or callbacks) that you might use from the UI. The simplest approach is for the library code to simply execute "as is", and if the UI happens to spawn it on a worker thread, then it is the UI's job to handle any events and marshal them (Control.Invoke/BeginInvoke) to the UI thread for UI updates.
For more complex scenarios, you can use the sync-context (SynchronizationContext.Current) to post messages to the UI thread (this is actually how Control.Invoke etc work, but it is implementation independent - so a WPF sync-context can go through the WPF dispatcher).
Can you add more context on what the scenario is? There are many things that can be done...
Write a interface for the EXE and have your main form or main class implement it.
Then register that object implementing the interface with the DLL.
Assign it to a variable of the that interface type
Make a Subroutine that is visible throughout the DLL.
In the Subroutine check to see if the variable is nothing if isn't then the subroutine that fires method you created to fire DoEvents.
Anytime you need to do a DoEvents then call the Subroutine.
If you are using a three tier organization for your application put the subroutine or variable on the object representing your entire application. Have the form register itself with the Application object.
If you have re-entrancy problems you can add status variable and other helper functions to safely check what the application is doing. Note that is far far easier to implements this if you are using some type of multi-tier design.
To other looking at this re-entrancy is a problem however so is a non-responsive UI. In a complex application there are circumstances where you have to let the event loop fire.

Categories