Click here to Skip to main content
15,885,366 members
Articles / Programming Languages / C#
Article

Loosely Coupled Event Driven Programming

Rate me:
Please Sign up or sign in to vote.
4.54/5 (10 votes)
6 Dec 20062 min read 47K   685   38   5
This article shows how to assign events dynamically, the main target is to make the application very loosely coupled.

Sample Image

Introduction

This article shows how to assign events dynamically, the target is to make the application very loosely coupled.

The code gives a brief idea on how to develop the application using Reflection, and how to dynamically associate methods to events.

Let me give a brief idea about the approach I followed. I have created two attributes and assigned the value of the attributes to be same for the event and the corresponding method. Dynamically, I am checking an event and trying to associate that event with the background method having the same attribute value. I will explain the step by step approach that I took. The first thing is we have to create two attributes (one for events and another for the methods).

C#
[AttributeUsage(AttributeTargets.Event)]
public class EventAtrributePublisher : Attribute
{
    private string _name;
    public EventAtrributePublisher(string name)
    {
        this._name = name;
    }
    public string Name
    {
        get
        {
            return this._name;
        }
    }
}

Same way, we have to create attributes for the publisher and make the attribute target as methods. Then, create custom event args, which we will be using while creating the event handler.

C#
public class ParameterEventArgs:EventAr{

Create any collection object inside the above method, which will maintain the data and which can be passed to the methods. Assign the created attributes to the events/methods:

C#
[EventAtrributePublisher("DynamicEventMethod")] 
 public  event EventHandler<ParameterEventArgs> DynamicEvent;
[EventAttributeSubscriber("DynamicEventMethod")] 
 public void MethodEventHandler(object sender, 
             ParameterEventArgs pe)
 {
    //Handle the method
 }

The next core thing is linking the event with the method. For that, I created a manager where we have two static collection objects (one for methods and another for events). First load the method handler library dynamically, by specifying the path of the assembly.

C#
Assembly.LoadFrom("MethodHandlerLibrary.dll")

This assembly has all the methods which get invoked while the associated event is raised. This assembly name can be configured in the application configuration file.

I have two static methods: AddSubscriber, PublishEvents, for adding method related stuff and event related stuff to the collection, respectively.

C#
PublishEvents(object instance)
{
    Type t = instance.GetType();
    EventInfo[] events = t.GetEvents();
    foreach (EventInfo e in events)
    {
        //Get only the events which are attributed 
        //with custom attribute "EventAtrributePublisher"
        EventAtrributePublisher attr = 
          (EventAtrributePublisher)Attribute.GetCustomAttribute(e, 
           typeof(EventAtrributePublisher), false);
        if (attr != null)
        {
            //This following method adds the related 
            //information to the collection object.
            AddEventPublishEvent(attr.Name, instance, e);
        }
}    

In the above code, instance is nothing but the main form of the application (i.e., this). Next, add the method related stuff to the collection that is there in a given assembly.

C#
public static void AddSubscriber(Assembly assembly)
{
    //We are interested in only the types 
    //which are visible from outside.
    Type[] allTypes = assembly.GetExportedTypes();
    if (allTypes != null)
    {
        foreach (Type t in allTypes)
        {
            if (t.IsClass)
            {
                MethodInfo[] mtCollection = t.GetMethods();
                foreach (MethodInfo m in mtCollection)
                {
                    //Get only the methods which are attributed 
                    //with "EventAttributeSubscriber"
                    EventAttributeSubscriber spa = 
                       (EventAttributeSubscriber)
                        Attribute.GetCustomAttribute(m,
                        typeof(EventAttributeSubscriber));
                    if (spa != null)
                    {
                        //Add method related stuff to the collection object.
                        AddEventSubscriber(spa.Name, t, m);
                    }
                }
            }
        }
    }
}

Next comes the linking of events to the methods. I have one more static method which links the publisher to the subscriber. For that, it makes use of the attribute value. Here, I am dynamically creating the delegate and adding that particular event handler to the published event.

C#
dlg = (Delegate)Activator.CreateInstance(pubEvent.EventHandlerType, 
       new object[] { instance, 
       mi.MethodHandle.GetFunctionPointer() });
//Can be done using Delegate.CreateDelegate also.
if (dlg != null)
 {
    pubEvent.AddEventHandler(pubInstance, dlg);
 }

The last step you have to take care of is, creating the custom event args object and invoking the required event.

C#
if (CustomEvent != null)
{
    Hashtable parameterCollection = new Hashtable();
    parameterCollection.Add("name", lblDynamic.Text);
    ParameterEventArgs pe = 
       new ParameterEventArgs(parameterCollection);
    CustomEvent(this, pe);
    lblDynamic.Text = pe.ParameterCollection["name"].ToString();
}

I tried to create the delegate using Delegate.CreateDelegate, but somehow I was not able to do that. I think we can create the delegate using Delegate.CreateDelegate as well.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Technical Lead Thomson Reuters
India India
completed B.Tech in computer science, working as Technical Leader.

Comments and Discussions

 
QuestionWhy would you want to do this? Pin
hain12-Dec-06 3:23
hain12-Dec-06 3:23 
AnswerRe: Why would you want to do this? Pin
karun12312-Dec-06 17:29
karun12312-Dec-06 17:29 
GeneralRe: Why would you want to do this? Pin
sashisme12-Dec-06 19:12
sashisme12-Dec-06 19:12 
Loose coupling is a nice thing, but have you thought about the performance implications? Using reflection KILLS performance. We had a similar implementation in our product where plug-ins are loaded by reflection and needless to say we had bad experience.
Secondly Microsoft uses a similar approach called the "Provider-Model design pattern". It may not be the exact same, but the idea is loose coupling. But even there it works because the object is cached after instantiation using reflection.
Third, we lose type fidelity. You'd have to cast everything from the hashtable. That's BAD for me and not acceptable in any commercial grade product.
GeneralCAB Pin
Urs Enzler11-Dec-06 20:56
Urs Enzler11-Dec-06 20:56 
GeneralRe: CAB Pin
karun12312-Dec-06 17:24
karun12312-Dec-06 17:24 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.