locked
How to instantiate an interface from a dynamically loaded assembly? RRS feed

  • Question

  • How can an interface be instantiated that is in a dynamically loaded assembly?

    Assume that three assemblies exist, one that is in command to the other two and defines the interface IExample. The second assembly, DecoupledAssembly, implements a class named Example which is derived from the interface IExample. The third is an application. It wants to load the DecoupledAssembly and then instantiate IExample.

    Here's what IExample looks like.

    public interface IExample
    {
        void Method1( string s );
    }
    

    Here's what the sample DecoupledAssembly looks like.

    namespace DecoupledAssembly
    {
        public class Example : IExample
        {
            public void Method1( string s )
            {
                Console.WriteLine( s );
            }
        }
    }
    

    Here's what the application that wants to instantiate the interface looks like.

    do { try { // Load the assembly. This works. System.Reflection.Assembly decoupledAssembly =
    System.Reflection.Assembly.LoadFrom( "DecoupledAssembly.dll" ); if (decoupledAssembly == null) { break; } // Load the interface. This fails. IExample example = decoupledAssembly.CreateInstance( "IExample" ) as IExample; if (example == null) { break; } } catch (Exception ex) { Console.WriteLine( ex.ToString() ); } } while (false);


    So, obviously, I am doing something wrong with extracting the interface out of the DecoupledAssembly. What would be the correct way to do this?


    Richard Lewis Haggard

    Monday, December 23, 2013 5:47 AM

Answers

  • Got it. Actually, it's remarkably easy to do. Once the assembly is loaded you can get a list of all of the types it contains. You can then itemize through those types and ask the type if it can support that interface. This can be done without actually instantiating an object. Once you find a type that says it supports the interface then you can ask the assembly to create that particular object and safe cast to the interface you want. A final paranoia check to see if the result is non-null and you are golden.

    // Cannot directly instantiate an interface. Can only
    // instantiate classes. However, we don't know the name
    // of the class that supports this interface so we have
    // to brute force search for it.
    Type[] types = decoupledAssembly.GetTypes();
    foreach ( Type type in types )
    {
        // Does this class support the transport interface?
        Type typeExample = type.GetInterface( "IExample" );
        if (typeExample == null)
        {
            // Not supported.
            continue;
        }
    
        // This class supports the interface. Instantiate it.
        IExample example = decoupledAssembly.CreateInstance( type.FullName ) as IExample;
        if ( example != null )
        {
            // Successfully created the interface. We are done.
            break;
        }
    }
    


    Richard Lewis Haggard


    Monday, December 23, 2013 3:39 PM

All replies

  • The problem is that you cannot create an instance of an Interface.  You must create a class which implements the Interface.


    Lloyd Sheen

    Monday, December 23, 2013 11:59 AM
  • You cannot create an instance of an interface but you can create an instance of the class that implements the interface. Just remember to include the namespace in the call to the CreateInstance method. The following should work if the calling code has a reference to the assembly where the IExample interface is defined:

                System.Reflection.Assembly decoupledAssembly = System.Reflection.Assembly.LoadFrom("DecoupledAssembly.dll");
                if (decoupledAssembly != null)
                {
                    IExample example = decoupledAssembly.CreateInstance("DecoupledAssembly.Example") as IExample;
                    if (example != null)
                    {
                        int d = 1;
                    }
                }
    

    Monday, December 23, 2013 1:59 PM
  • Thanks, that makes sense. However, it doesn't solve the intent of what I was trying to do which is to create a simple decoupling method so that I could roll my own dependency injection or plug in support. If the caller has to know namespace and class details then the whole decoupling thing is mute.

    If it is not possible to directly request the interface itself then perhaps it would be possible to use a brute force solution. Get a collection of all available classes and then instantiate them one at a time and attempt to convert to the target interface. The first one that succeeds is the one that we want. Sounds potentially time consuming but doable on first glance.


    Richard Lewis Haggard


    Monday, December 23, 2013 3:05 PM
  • Got it. Actually, it's remarkably easy to do. Once the assembly is loaded you can get a list of all of the types it contains. You can then itemize through those types and ask the type if it can support that interface. This can be done without actually instantiating an object. Once you find a type that says it supports the interface then you can ask the assembly to create that particular object and safe cast to the interface you want. A final paranoia check to see if the result is non-null and you are golden.

    // Cannot directly instantiate an interface. Can only
    // instantiate classes. However, we don't know the name
    // of the class that supports this interface so we have
    // to brute force search for it.
    Type[] types = decoupledAssembly.GetTypes();
    foreach ( Type type in types )
    {
        // Does this class support the transport interface?
        Type typeExample = type.GetInterface( "IExample" );
        if (typeExample == null)
        {
            // Not supported.
            continue;
        }
    
        // This class supports the interface. Instantiate it.
        IExample example = decoupledAssembly.CreateInstance( type.FullName ) as IExample;
        if ( example != null )
        {
            // Successfully created the interface. We are done.
            break;
        }
    }
    


    Richard Lewis Haggard


    Monday, December 23, 2013 3:39 PM
  • I would like to recommend the link 

    http://goldcing.blogspot.com/2014/03/how-to-dynamically-turn-onoff-tool-item.html

    . It is pretty cool way.
    Monday, March 24, 2014 3:26 AM