Transparent Proxy Service Locator

Quick Note: Just published a quick release of a service locator pattern that uses a transparent proxy to invoke the methods on all implementations of a service without the visibility there may be more than one instance of the service.

It’s probably not the best fit for a full service locator pattern, but using the transparent proxy to intercept the method calls will definitely find a use somewhere! 


Plugin based development

Plugin based development

I’m currently working on a software project for a well known Church based over in Los Angeles where we are installing an online ordering portal, the site in question uses ASP NET Webforms, but is an LOB (Line of Business) application used by many over vendors in our market. We need to integrate with the customer at the payment stage in order to:

  1. Update their internal system with the information from our system.
  2. Collect payment for the order.


As we need this system to be totally independent of our core system, we need to be able to reference these “Plugins” from an outside source, but we need to know what these interfaces actually do!

The answer is simple. Interfaces.

An interface is a method of declaring what properties, methods a particular CLR type is compatible with. Most of us use this without knowing about it every day, when you use:

For Each item in collection
Next item

You are actually referencing the IEnumerable(Of T) interface, which tells the compiler I am able to Enumerate and yield a value several times from this object.

So, we’ve decided that we need an Interface, but how do we actually load these dll’s at run time? It can be a big question at first, (it was for me) – but after consulting with Dr. Google I found the classes I needed.

First, System.Assembly. It provides us with all the gubbins we need to load and inspect an assembly dynamically at run time.

assemblyToLoad = System.Reflection.Assembly.LoadFile(file)

This function will physically load the CLR with this assembly, in order for us to inspect it using the System.Type class.

Dim interfaces() As System.Type
interfaces = assemblyToLoad.GetExportedTypes()

So a couple things to note on the above example, first, we are using “GetExportedTypes.” The reason you want this method is because it only returns the types that are availiable to anything external. If you use the other methods, you may find more interface implementations than you were supposed to, or, you’ll find internal .NET generated classes like MySettings classes. Public declarations were invented for a reason – Make sure you use them correctly!

So, if we put what we know together we could make this a nice generic function, and for extra type safety we include a base “IPlugin” interface, it allows us both sides to ensure the class/interface we are loaded was meant to be a plugin. Here’s the code in full:

Public Class Plugins

    Public Interface IPlugin
        Property AssemblyPath As String
    End Interface

    Public Shared Function EnumerateFolder(Of T As IPlugin)(ByVal directory As String) As List(Of T)
        Dim assembly As Reflection.Assembly
        Dim foundPlugins As New List(Of T)
        Dim types() As Type
        Dim filter As Reflection.TypeFilter
        Dim plugin As T

        filter = New Reflection.TypeFilter(Function(m As Type, criteria As Object)
                                               Return True
                                           End Function)

        For Each file In IO.Directory.EnumerateFiles(directory, "*.dll", IO.SearchOption.TopDirectoryOnly)
                assembly = System.Reflection.Assembly.LoadFile(file)

                For Each foundType As System.Type In assembly.GetExportedTypes
                    types = foundType.FindInterfaces(filter, Nothing)

                    If types.Contains(GetType(T)) And types.Contains(GetType(IPlugin)) Then
                        plugin = Activator.CreateInstance(foundType)
                        plugin.AssemblyPath = file
                    End If

            Catch ex As Exception
                'not a .net assembly
            End Try

        Return foundPlugins
    End Function

End Class