• MEF, MAF and all C# Plugins in-between

    by  • January 14, 2012 • Journal • 1 Comment

    Over the years one of the most common things people try to implement using a language is the concept of plugins to extend an application, some languages or frameworks do this easily and some can be a bit more tricky; I’m looking at you COM.

    Being aimed at the business application .NET has needed this functionality as well, and so has spawned many different approaches, each with their strengths and weaknesses.

    First off I’ll talk about the Managed Add-in Framework (MAF) which usually is referred to as System.Addin it was designed to abstract the creation of plugins and provide the ability to adjust the security imposed on the plugins assembly reference and underlying AppDomain, this was great for businesses that could define Interfaces in a design by contract fashion.

    The problem is for regular users that want a quicker, alas inherently naive plugin mechanism.

    For all plugins, the underlying CLR uses reflection to determine eligibility of a plugin, thus you can write your own of you can guarantee certain characteristics of your plugin, or security issues across AppDomains is not a concern.

    I decided to see what the bare minimum was to write a plugin manager, here it is below, I’ll go on to explain its concepts afterwards.

            public static void LoadPluginsFromFile(FileInfo file, out List availablePlugins)
            {
                availablePlugins = new List();
    
                Assembly caller = null;
                try
                {
                    caller = Assembly.LoadFile(file.FullName);
                }
                catch
                {
                    // Unable to load Assembly
                    return;
                }
    
                // Check for Runtime Mismatch between assemblies
                if (caller != null && caller.ImageRuntimeVersion.Equals(Assembly.GetExecutingAssembly().ImageRuntimeVersion))
                {
                    foreach (Type t in caller.GetTypes())
                    {
                        if (typeof(T).IsAssignableFrom(t) && !t.Equals(typeof(T)))
                        {
                            try
                            {
                                availablePlugins.Add((T)caller.CreateInstance(t.ToString()));
                            }
                            catch
                            {
                                // Invocation failure on the Plugin
                            }
                        }
                    }
                }
            }
    

    The code above is a generic method which loads in plugins using an underlying Base Class or Interface of type T from a specified file. It performs checks to see whether the Assembly can be loaded correctly and whether the Assembly Image Format – The reference to the CLR version the code was compiled against is valid. Once the assembly has been checked, the Assembly is scanned for Classes that use the Type which our plugin inherits from, if any are found they are instantiated and returned as part of a list.

    The code can be extended to add additional checks and include security around the Plugins Assembly AppDomain. Try it out.

    While coding this I noticed an interesting problem inherent in reflection, you can’t dynamically cast a generic type while dynamically invoking a generic method via reflection because you can not late bind generic methods (Invoking via reflection). For example this over the top example fails to invoke.

            static void Main(string[] args)
            {
                Program p = new Program();
                object o = p.CreateGenericWrapper(typeof(List<>), typeof(string), new string[] { "a", "b" });
            }
    
            public object CreateGenericWrapper(Type t, Type u, params object[] args)
            {
                MethodInfo castMethod = this.GetType().GetMethod("CreateGeneric").MakeGenericMethod(t,u);
                return castMethod.Invoke(null, new object[] { args });
            }
    
            public object CreateGeneric<T,U>(params object[] args)
            {
                return Activator.CreateInstance(typeof(T).MakeGenericType(new System.Type[] { typeof(U) }), args);
            }
    

    To explain, the above code is attempting to dynamically at runtime create a generic list of strings via invoking a generic method with the inferred type information.

    In .NET 4 Microsoft upgraded the framework and renamed it, to become the Managed Extensibility Framework (MEF). The main difference was that MAF was designed to be high level, to provide a mechanism to provide isolation and security, and of course loading and unloading. MEF takes this further and provides additional mechanism for discoverability, extensibility, and portability. The advantage of this is that the two frameworks can be used in union with each other.

    MSDN provides a great detail of information on MEF as well as an example project to download and try.

    About

    Software engineer. Tea drinker

    http://MrPfister.com

    One Response to MEF, MAF and all C# Plugins in-between

    1. Pingback: Bug Fixing and Tracking with Reflection | Mr Pfisters Random Waffle

    Leave a Reply

    Your email address will not be published. Required fields are marked *