Dynamically load a DLL from a specific folder?

19,477

Solution 1

Once you call this line

var shellViewLibrary = Assembly.LoadFrom(Path.Combine(_DllsPath, _DllShellView)); 

The assembly has been loaded in to memory. So long as you specify types correctly from this then you will be able to use Activator.CreateInstance to create the types. ie: It is not necessary to further specify where the type is.

Regarding Activator, from MSDN the CreateInstance method can accept a System.Type. I would just use this method inside your if-statement:

Activator.CreateInstance(Type type);

What I would try to do to debug this is first create the type and then pass it in to CreateInstance. You may find that the Type creation itself is failing (due to unresolved assembly) or the instantiation of that type (due to exception in the constructor). At first glance your code here appears to be correct:

foreach (Type type in types)      
{          
    var typeIShellViewInterface = type.GetInterface(_NamespaceIShellView, false);          
    if (typeIShellViewInterface != null)          
    {              
        try
        {
            // I assume you are calling this line at the point marked 'here'. 
            // To debug the creation wrap in a try-catch and view the inner exceptions
            var result = Activator.CreateInstance(type);          
        }
        catch(Exception caught)
        {
            // When you hit this line, look at caught inner exceptions
            // I suspect you have a broken Xaml file inside WPF usercontrol
            // or Xaml resource dictionary used by type
            Debugger.Break();
        }
    }      
}  

In your question you specify that you are getting a XamlParseException. It sounds to me like the type in question is a UserControl (or otherwise refers to a WPF Xaml resource file) and there is an error in that Xaml file, i.e. nothing to do with your usage of Assembly.Load or Activator.CreateInstance.

Could you try posting the inner exception(s) to get a better idea on what the problem is?

Solution 2

This is an example of "Dynamically Loading a .dll from a Specific Folder" at runtime.

// Check if user has access to requested .dll.
string strDllPath = Path.GetFullPath(strSomePath);
if (File.Exists(strDllPath))
{
    // Execute the method from the requested .dll using reflection (System.Reflection).
    Assembly DLL = Assembly.LoadFrom(strDllPath);
    Type classType = DLL.GetType(String.Format("{0}.{1}", strNmSpaceNm, strClassNm));
    if (classType != null)
    {
        // Create class instance.
        classInst = Activator.CreateInstance(classType);

        // Invoke required method.
        MethodInfo methodInfo = classType.GetMethod(strMethodName);
        if (methodInfo != null)
        {
            object result = null;
            result = methodInfo.Invoke(classInst, new object[] { dllParams });
            return result.ToString();
        }
    }
}

This took me a while to work out so I hope it is of some use...

Solution 3

Check out MEF and Prism. MEF is a dependency injection library that helps with this. You can load all of your dependencies from a specific folder and make dynamically load them.

Prism is a pattern that leverages dependency injection and works great with MEF to load libraries dynamically

Share:
19,477
Guillaume Slashy
Author by

Guillaume Slashy

Software Developer

Updated on June 04, 2022

Comments

  • Guillaume Slashy
    Guillaume Slashy almost 2 years

    At the moment, I have this code :

    var shellViewLibrary = Assembly.LoadFrom(Path.Combine(_DllsPath, _DllShellView));
    IEnumerable<Type> types = shellViewLibrary.GetTypes();
    
    foreach (Type type in types)
    {
        var typeIShellViewInterface = type.GetInterface(_NamespaceIShellView, false);
        if (typeIShellViewInterface != null)
        {
            //here
        }
    }
    

    The thing is that where I got //here I want to use Activator.CreateInstance to create an object whose type is type in a specific folder (that is outside the build folder) I tried about 20 different things, most of them with this : http://msdn.microsoft.com/en-us/library/d133hta4.aspx but none works... The typical thing I tried is :

    object MyObj = Activator.CreateInstance(shellViewLibrary.FullName, type.FullName);
    

    or

    object MyObj = Activator.CreateInstance(Path.Combine(_DllsPath, _DllShellView), type.FullName);
    

    I always got different exception, the most common being :

    XamlParseException
    

    I feel like that I'm not using Activator.CreateInstance in the right way with 2 parameters. What should I do ?

  • Guillaume Slashy
    Guillaume Slashy over 12 years
    When I do var lib = Assembly.LoadFile("D:\\CebisSample\\Runtime\\myDLL.dll"); I got the same XAML error, what's wrong ? When I do LoadFrom from the exact same dll, it works oO
  • Guillaume Slashy
    Guillaume Slashy over 12 years
    If my assembly is on a USB-key for example, Activator.CreateInstance won't work if I don't specify something, no ?
  • codingbunny
    codingbunny over 12 years
    LoadFile examines the 'identity' of the DLL and validates the versions of the assemblies whereas LoadFrom doesn't do this and just grabs the matching version. LoadFile allows you to load different versions of assemblies.
  • Dr. Andrew Burnett-Thompson
    Dr. Andrew Burnett-Thompson over 12 years
    If you read the q. carefully you'll see he's already got the type and assembly loaded
  • codingbunny
    codingbunny over 12 years
    He added that, it wasn't there originally. So thank you, but I've read the question
  • Guillaume Slashy
    Guillaume Slashy over 12 years
    Thats' the code I did in the 1st time and it fails at classInst = Activator.CreateInstance(classType); for me :/ Maybe something's wrong with the dll...
  • Randolpho
    Randolpho over 12 years
    Once you load the assembly, it's in memory. There are rules .NET has about loading assemblies from remote drives (I misremember them at the moment, but I will look them up), but once the assembly is loaded, Activator.CreateInstance will instantiate types for you, provided you tell it what type you want to instantiate.
  • MoonKnight
    MoonKnight over 12 years
    It should give you a good indication of what is going wrong if you step through the code in debug mode. You also need to know the Namespace name and Class name you are invoking using this method. Additionally, the above code is passing parameters to the .dll. If you do not know what parameters to pass the called function this can also be an issue...