Cross module communication with Autofac Part 1

By Deathraven on Saturday 23 April 2011 11:30 - Comments (2)
Category: Software Development, Views: 4.130

The next series of blogs is going to be about creating an system that allows cross module communication while preventing said module(s) from having a direct dependency on each other.

Lets elaborate on that.
Whenever your building an application architecture that has the notion of plugin's or multiple seperate modules, whose composition define the functionality of your application. You are likely to run into the problem where you need to create an architecture that allows modules from extending the base behavior of your application.

My system went through multiple iterations, i am going to start with explaining the first, and then expanding on the second in the next blogpost.

Ofcourse there are more ways then one to do this. But the idea that I had was that I wanted a module to be able to throw some kind of event, that would possibly trigger logic in other modules. This way I would have a lightweight way to create core processes in my system, that are still extensible by other modules.

So I started by creating the IEventHandler interface

C#:
1
public interface IEventHandler {}



Its nothing more then a marker interface we are going to use for registration in Autofac. Because thats what I use in all my projects :P When loading the modules i scan for implementations of the IEventHandler and register those in the container.
Pseudo code for that would be something like this:

C#:
1
2
3
4
5
6
7
8
//or use autofac assembly scanning functionality
var registrations = moduleAssembly.GetTypes().Where(t => typeof(IEventHandler).IsAssignableFrom(t));
foreach(var item in registrations)
{
    autofacContainerBuilder.RegisterType(item)
                    .As<IEventHandler>()
                    .InstancePerDependency();
}



The next step is creating an event specific interface. Lets say for example that we want modules to do stuff as the application is starting up or closing itself down.

C#:
1
2
3
4
5
public interface IEnvironmentContextEvents : IEventHandler {
        void Initializing();
        void Initialized();
        void Terminating();
}



Because this will be registered in Autofac this gives us some interesting capability's. For example now i can do this:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class MyApplication
{
      private IEnumerable<IEnvironmentContextEvents> handlers;

      public MyApplication(IEnumerable<IEnvironmentContextEvents> handlers)
      {
              this.handlers = handlers;
      }

      public void Startup()
      {
           [..] //do something

           handlers.ForEach(x => x.Initializing()); //ofcourse we can also specifiy some context we are going to pass to the handler           

           [..] //do some more

           handlers.ForEach(x => x.Initialized()); 
      }
}



This is already very close to what we are trying to achieve. However there are some issues with it.
  • I might want to do some error handler to prevent errors from a handler to stop execution of the Startup process
  • I really dont want to have to iterate through all handlers every time.
So clearly I needed some kind of abstraction for this in which I could solve these problems. Eventually I came up with something that enabled me to do this..

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class MyApplication
{
      private IEventBus<IEnvironmentContextEvents> eventBus;

      public MyApplication(IEventBus<IEnvironmentContextEvents> eventBus)
      {
              this.eventBus = eventBus;
      }

      public void Startup()
      {
           [..] //do something
           
           eventBus.Call(x => x.Initializing());

           [..] //do some more

           eventBus.Call(x => x.Initialized());
      }
}



The IEventBus<T> is an really easy implementation of an generic class that takes an dependency on an IEnumerable<T> constrained on IEventHandler. Simple, but effective.
That is.. until I started delving into the sourcecode of OrchardCMS.

More on that in Part 2

Volgende: Fluentnhibernate AttributePropertyConvention 06-'13 Fluentnhibernate AttributePropertyConvention
Volgende: The age of NuGet 01-'11 The age of NuGet

Comments


By Tweakers user RobIII, Tuesday 4 June 2013 13:09

Where's part 2? :P

By Tweakers user Deathraven, Tuesday 4 June 2013 14:33

Ahaha, I knew that was coming back to haunt me. :D

In Orchard they are using a proxy in combination with autofac. That way you can take an dependency on the IEventHandler type itself, and the proxy would handle the whole eventbus thing.

But there is alot going on, and thus alot to explain. At that time I got really busy with other stuff and could not be arsed after that :P

Comments are closed