RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Design for Extensibility : Page 6

Build extensibility and flexibility into your applications to simplify maintenance and accommodate changes.

Adding Extensibility to the Client
The client will also have to be changed. To support multiple plug-ins, instead of having the client look for a specific plug-in type to instantiate, it will read in all the modules, and loop through them, calling each one's Initialize method. That process will build the invocation lists of any delegates I've wired in any of the modules.

   ' In VB:
   Dim section As Object = _
      ConfigurationManager.GetSection( _
   Dim o_Modules As List(Of String) = _
      DirectCast(section, List(Of String))
   Dim o_FilterEvents As New ModuleEvents()
   For Each s_ModuleType As String _
      In o_Modules
      Dim o As Object = _
         Activator.CreateInstance( _
      Dim o_Module As IAcmeModule = _
         DirectCast(o, IAcmeModule)
   // In C#:
   object section = 
   List<string> o_Modules = section as 
   ModuleEvents o_FilterEvents = new 
   foreach (string s_ModuleType in 
      object o = 
      IAcmeModule o_Module = o as 
Notice that the preceding code declares the o_FilterEvents ModuleEvents object outside the loop, and sends the same object to each module. This way, by the end of the loop, the delegate properties in the object may contain zero or more method pointers.

All this happens somewhere near the beginning of my application, but I still have to decide where to insert extensibility points within the body of the application, just like the earlier example called the IPostLogPlugin-based classes from a specific point in the application.

Upon making these decisions, I'll check for the property in o_FilterEvents that corresponds to the extensibility point within my application. Checking that property for a value other than null (Nothing in VB.NET) is enough to determine whether there are items in the invocation list for the delegate. At that point, it simply becomes a matter of invoking the delegate. The following is the extensibility point inserted just after I obtained a "data source" (remember the GetSource method):

   'In VB:
   Dim b_Cancel As Boolean = False
   If Not o_FilterEvents.CheckDataSource _
      Is Nothing Then
      Dim o_EventArgs As _
         CheckDataSourceEventArgs = _
         New CheckDataSourceEventArgs(s_Source)
      o_FilterEvents.CheckDataSource.Invoke( _
      b_Cancel = o_EventArgs.Cancel
   End If
   //In C#:
   bool b_Cancel = false;
   if (o_FilterEvents.CheckDataSource != null)
      CheckDataSourceEventArgs o_EventArgs = 
         new CheckDataSourceEventArgs(s_Source);
      b_Cancel = o_EventArgs.Cancel;
Note the Boolean variable declared before this event fires, which is set to the Cancel value that comes back from the EventArgs class. I've designed this event so that the code you can inject has the option to set the Cancel property to true or false. An example of code that taps into this event would look like this:

   'In VB:
   Public Class ProfanityFilter
      Implements IAcmeModule
      Public Sub Initialize( _
         ByVal events As _
         Core.ModuleEvents) _
         events.CheckDataSource = New _
            AcmeModuleDelegate(Of _
           (AddressOf events_CheckDataSource)
      End Sub
      Private Sub events_CheckDataSource( _
         ByVal e As CheckDataSourceEventArgs)
         If e.Source.ToUpper().IndexOf("BAD") _
            > -1 Then
            e.Cancel = True
         End If
      End Sub
   End Class
   / In C#:
   public class ProfanityFilter : 
      void IAcmeModule.Initialize(
         ModuleEvents events)
         events.CheckDataSource += 
      void events_CheckDataSource(
         CheckDataSourceEventArgs e)
         if (e.Source.ToUpper().IndexOf("BAD") > -1) 
            e.Cancel = true;
This module taps into the CheckDataSource event and checks to see if the data source coming in contains the word "BAD." If so, it sets the Cancel property to true. Now the code added to the client earlier that worked with the b_Cancel variable should make more sense. Code that follows the preceding example would check the value of b_Cancel to determine if it should continue processing.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date