How to: C# Connect to dynamic event

In our WCF services we have used the DbProviderFactories and the default interface so that our WCF services has no direct reference to the actual database provider or version. Recently we needed to connect to the InfoMessage event on the TeraData database provider without knowing the actual type. We wanted to still remain on the path with no reference to the driver and this was not straight forward. With the inspiration fro0m http://stackoverflow.com/questions/45779/c-sharp-dynamic-event-subscription we adapted a solution with Expression trees and in case you need to dynamically hook into an event, here is how we did it:

 1: namespace DynamicEvent
 2: {
 3:   internal class Program
 4:   {
 5:     private static void Main(string[] args)
 6:     {
 7:       var connectionString = "Your connection string here!";
 8:       var factory = DbProviderFactories.GetFactory("Teradata.Client.Provider");
 9:       var conn = factory.CreateConnection();
 10:       conn.ConnectionString = connectionString;
 11:       conn.Open();
 12:  
 13:       EventInfo ev = conn.GetType().GetEvent("InfoMessage");
 14:       var handler = EventProxy.Create(ev, HandleInfoMessage);
 15:       // add event handler 
 16:       ev.AddEventHandler(conn, handler);
 17:       try
 18:       {
 19:         // run sql call
 20:  
 21:  
 22:       }
 23:       finally
 24:       {
 25:         // unhook event handler 
 26:         ev.RemoveEventHandler(conn, handler);
 27:       }
 28:     }
 29:  
 30:     static void HandleInfoMessage(object obj, EventArgs eventArgs)
 31:     {
 32:       // Use Fasterflect, http://fasterflect.codeplex.com to dynamically access properties on the EventArgs object.
 33:       Console.WriteLine("InfoMessage {0}:{1}", obj.GetType().ToString(), eventArgs.GetType().ToString());
 34:     }
 35:   }
 36:  
 37:   public class EventProxy
 38:   {
 39:     public static Delegate Create(EventInfo evt, Action<object, EventArgs> d)
 40:     {
 41:       var handlerType = evt.EventHandlerType;
 42:       var eventParams = handlerType.GetMethod("Invoke").GetParameters();
 43:  
 44:       var parameters = eventParams.Select(p => Expression.Parameter(p.ParameterType, "x")).ToArray();
 45:       var body = Expression.Call(Expression.Constant(d), d.GetType().GetMethod("Invoke"), parameters[0], parameters[1]);
 46:       var lambda = Expression.Lambda(body, parameters.ToArray());
 47:       return Delegate.CreateDelegate(handlerType, lambda.Compile(), "Invoke", false);
 48:     }
 49:   }
 50: }

You could use this EventProxy and technique to hook into any event where the signature is (object, EventArgs) or any other class that descends from EventArgs.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s