Click here to Skip to main content
Click here to Skip to main content

Pluggable Remote Object Hosting

, 11 Nov 2003
Rate this:
Please Sign up or sign in to vote.
This article presents a Pluggable mechanism for the identification and hosting of .NET Remote objects.

Introduction

Back in the old days when I programmed with Visual C++ and DCOM, one of my favorite features was ‘Component Categories’. For those of you who are unfamiliar with DCOM, categories allowed the component developer to dynamically add behavior to an application by supporting a common interface and GUID pair. On application start-up, all registered components who supported a particular GUID could be identified and instantiated and subsequently communicated with via the common interface.

So far I have been unable to identify an equivalent in .NET Remoting, however after reading an article on .NET Reflection here on Code Project (the original source for which I can’t find but if you think you’re the author then contact me and I’ll give you your due credit), I think I’ve come up with something just as flexible.

Reflection

Reflection is nothing new to the Java development community, the basic idea is that metadata for all managed types can be accessed at runtime. This gives the developer the ability to interrogate the inheritance hierarchy of an object, invoke methods similar to IDispatch invoke, but most importantly to instantiate an object from its metadata definition. Couple this with the .NET ability to interrogate the exposed managed object types contained within a particular assembly, and you have the fundamental building blocks for a ‘Component Category’ alternative.

At this point, I’d like to point out that this Plugin API should not be seen as only applicable to Remote Object hosting. In fact, at the moment I use the API to add a vertical slice of functionality to my application space, from Menu options and Wizards to backend servers.

Plugin API

The basic Plugin API is quite simple; a PluginManager class is provided which takes a ‘Plugin Interface Type’ and can then return all the objects contained within the current working directory supporting that interface. The reason for the indirection between the Plugin interface and the Plugin object is that I wanted to be able to control the instantiation of the Plugin object, possibly through the use of a sub-class of the basic PluginManager class.

public interface IPlugin
{
    Type PluginInterface {get;}
}
 
public class PluginManager
{
...
    public virtual ArrayList GetPlugins(Type pluginType)
    {
        if(pluginType ==null)
        {
            Console.WriteLine("The plugin type was not set");
            return new ArrayList(0);
        }
        try
        {
            string currentDirectory = 
                System.AppDomain.CurrentDomain.BaseDirectory;
            string[] pluginFilenames = Directory.GetFiles(
                currentDirectory, @“*.dll“);
            ArrayList plugins = new ArrayList();
            foreach(string pluginFilename in pluginFilenames)
            {
                Assembly assembly = Assembly.LoadFrom(pluginFilename);
                Type[] assemblyPlugins = assembly.GetExportedTypes();
                foreach(Type plugin in assemblyPlugins)
                {
                    if(plugin.GetInterface(pluginType.FullName)==null)
                    {
                        continue;
                    }
                    plugins.Add(Activator.CreateInstance(plugin));
                }
            }
            return plugins;
        }
        catch(BadImageFormatException bife)
        {
            Console.WriteLine(bife.ToString());
            return new ArrayList(0);
        }
    }
}

Remote Plugin API

The Remote Plugin API is basically a standardization on the definition of a Plugin interface and the creation of a custom Remote Plugin Manager.

The Remote Plugin Interface

public interface IRemotePlugin : IPlugin
{
    string ObjectUri {get;}
    WellKnownObjectMode ActivationType {get;}
}

The Remote Plugin Manager then delegates to the base Plugin Manager to identify the available plugins and subsequently register the objects for hosting within the current App Domain.

public class RemotePluginManager : PluginManager
{
...
    public void RegisterPlugins()
    {
        ArrayList plugins = this.GetPlugins(typeof(IRemotePlugin));
        foreach(IRemotePlugin plugin in plugins)
        {
            RemotingConfiguration.RegisterWellKnownServiceType(
                plugin.PluginInstance,
                plugin.ObjectUri,
                plugin.ActivationType);
        }
    }
}

Generic Hosting Application

The creation of a generic hosting application to use this Remote Plugin Manager is then relatively straight forward. On startup, standard Remote objects can be configured using the normal XML configuration file followed by pluggable object configuration via the Remote Plugin Manager.

class RemoteHostApp
{
    [STAThread]
    static void Main(string[] args)
    {
        try
        {
            Console.Write("Remote Host Application Starting ");
            Console.Write(DateTime.Now.ToLongDateString() + ":");
            Console.WriteLine(DateTime.Now.ToLongTimeString());
 
            RemotingConfiguration.Configure("RemoteHostApp.exe.config");
                          
            RemotePluginManager pluginManager = 
                new RemotePluginManager();
            pluginManager.RegisterPlugins();
 
            ShowWellKnownServices();
 
            System.Console.Write("Hit any key to exit: ");
            System.Console.ReadLine();
 
            Console.Write("CMS Server stopped ");
            Console.Write(DateTime.Now.ToLongDateString() + ":");
            Console.WriteLine(DateTime.Now.ToLongTimeString());
        }
        catch(Exception e)
        {
            Trace.WriteLine(e);
        }
    }
...
}

Deployment

All that needs to be done to deploy a new Remote object is to copy the DLL assembly into the working directory of the RemoteHostApp application. The hosting app presented here is very simple in that, to pick up the new Remote object it would have to be restarted. A very simple improvement to overcome this necessity would be to create a directory listener to detect when new files are added and existing one deleted.

Summary

In itself the Pluggable Remote API isn’t much of an improvement over the XML Deployment file, however when the pluggable concept is taken straight through to the GUI level, it becomes possible to add complete vertical slices of functionality to a core platform.

Downloads

Note: Source and demo projects have been created using #Develop.

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

Share

About the Author

David Boland
Web Developer
United States United States
No Biography provided

Comments and Discussions

 
QuestionWhat about the Client? PinmemberrEgEn2k3-Jun-06 10:25 
AnswerRe: What about the Client? PinmemberDavid Boland9-Jun-06 4:46 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.141223.1 | Last Updated 12 Nov 2003
Article Copyright 2003 by David Boland
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid