Can I load a .NET assembly at runtime and instantiate a type knowing only the name?
Asked Answered
P

13

188

Is it possible to instantiate an object at runtime if I only have the DLL name and the class name, without adding a reference to the assembly in the project? The class implements a interface, so once I instantiate the class, I will then cast it to the interface.

Assembly name:

library.dll

Type name:

Company.Project.Classname


EDIT: I dont have the absolute path of the DLL, so Assembly.LoadFile won't work. The DLL might be in the application root, system32, or even loaded in the GAC.

Predella answered 21/1, 2009 at 14:20 Comment(0)
S
232

Yes. You need to use Assembly.LoadFrom to load the assembly into memory, then you can use Activator.CreateInstance to create an instance of your preferred type. You'll need to look the type up first using reflection. Here is a simple example:

Assembly assembly = Assembly.LoadFrom("MyNice.dll");

Type type = assembly.GetType("MyType");

object instanceOfMyType = Activator.CreateInstance(type);

Update

When you have the assembly file name and the type name, you can use Activator.CreateInstance(assemblyName, typeName) to ask the .NET type resolution to resolve that into a type. You could wrap that with a try/catch so that if it fails, you can perform a search of directories where you may specifically store additional assemblies that otherwise might not be searched. This would use the preceding method at that point.

Springer answered 21/1, 2009 at 14:28 Comment(6)
I dont have the absolute path of the dll, so assemlby.LoadFile ect. wont work, any other ideas ?Predella
@MegaByte: LoadFrom is different to LoadFile. It will resolve your dependencies and it should resolve the DLL name from known paths (GAC, exe directory, etc.) See MSDN for more information.Springer
@MegaByte: Use Directory.GetCurrentDirectory() to get it.Weinberg
One more thing... (me again) Um, you can't just have "MyType" as the type name, it must be followed by NAMESPACE. So this would be more accurate: Type type = assembly.GetType("MyNamespace"+"."+"MyType");Weinberg
@Cipi: Technically, a type is it's full namespaced name (the concept of namespace is a language convenience). You can have a type with no namespace within the CLR - I was just providing an overly simplified example.Springer
It arises exception if I want to load system libraries (e.g. System.Drawing). Exception is like "Could not load file or assembly 'path_to_project\System.Drawing'..." or "...\System.Drawing.dll'..."Mortie
P
35

Consider the limitations of the different Load* methods. From the MSDN docs...

LoadFile does not load files into the LoadFrom context, and does not resolve dependencies using the load path, as the LoadFrom method does.

More information on Load Contexts can be found in the LoadFrom docs.

Portis answered 21/1, 2009 at 14:46 Comment(0)
F
19

Activator.CreateInstance ought to work.

IFace object = (IFace)Activator.CreateInstance( "AssemblyName",
                                                "TypeName" )
                               .Unwrap();

Note: The type name must be the fully qualified type.

Example:

var aray = (IList)Activator.CreateInstance("mscorlib","System.Collections.ArrayList").Unwrap();
aray.Add(10);

foreach (object obj in aray)
{
    Console.WriteLine(obj);
}
Fayefayette answered 21/1, 2009 at 14:24 Comment(1)
Just a note on this: TypeName must be fully qualified. I had to call this like: Activator.CreateInstance("MyAssembly","MyAssembly.TypeName") And that returns an ObjectHandle. To get down to your interface you need to do ObjectHandle.UnWrap()Trice
R
7

I found this question and some answers very useful, however I did have path problems, so this answer would cover loading library by finding bin directory path.

First solution:

string assemblyName = "library.dll";
string assemblyPath = HttpContext.Current.Server.MapPath("~/bin/" + assemblyName);
Assembly assembly = Assembly.LoadFrom(assemblyPath);
Type T = assembly.GetType("Company.Project.Classname");
Company.Project.Classname instance = (Company.Project.Classname) Activator.CreateInstance(T);

Second solution

string assemblyName = "library.dll";
string assemblyPath = HttpContext.Current.Server.MapPath("~/bin/" + assemblyName);
Assembly assembly = Assembly.LoadFile(assemblyPath);
(Company.Project.Classname) instance = (Company.Project.Classname) assembly.CreateInstance("Company.Project.Classname");

You can use same principle for interfaces (you would be creating a class but casting to interface), such as:

(Company.Project.Interfacename) instance = (Company.Project.Interfacename) assembly.CreateInstance("Company.Project.Classname");

This example is for web application but similar could be used for Desktop application, only path is resolved in different way, for example

Path.GetDirectoryName(Application.ExecutablePath)
Raft answered 17/2, 2012 at 17:45 Comment(0)
R
7

It's Easy.

Example from MSDN:

public static void Main()
{
    // Use the file name to load the assembly into the current
    // application domain.
    Assembly a = Assembly.Load("example");
    // Get the type to use.
    Type myType = a.GetType("Example");
    // Get the method to call.
    MethodInfo myMethod = myType.GetMethod("MethodA");
    // Create an instance.
    object obj = Activator.CreateInstance(myType);
    // Execute the method.
    myMethod.Invoke(obj, null);
}

Here's a reference link

https://msdn.microsoft.com/en-us/library/25y1ya39.aspx

Rangy answered 2/5, 2016 at 12:28 Comment(1)
That's a horrible way to support dynamic loading of code. MS has always liked to force us to get into way too many details.Fitter
B
5

Starting from Framework v4.5 you can use Activator.CreateInstanceFrom() to easily instantiate classes within assemblies. The following example shows how to use it and how to call a method passing parameters and getting return value.

    // Assuming moduleFileName contains full or valid relative path to assembly    
    var moduleInstance = Activator.CreateInstanceFrom(moduleFileName, "MyNamespace.MyClass");
    MethodInfo mi = moduleInstance.Unwrap().GetType().GetMethod("MyMethod");
    // Assuming the method returns a boolean and accepts a single string parameter
    bool rc = Convert.ToBoolean(mi.Invoke(moduleInstance.Unwrap(), new object[] { "MyParamValue" } ));
Boggle answered 27/2, 2017 at 14:24 Comment(0)
I
4
Assembly assembly = Assembly.LoadFrom("MyAssembly.dll");

Type type = assembly.GetType("MyType");

dynamic instanceOfMyType = Activator.CreateInstance(type);

So in this way you can use functions not with getting methodinfo,and then invoking it.You will do like this instanceOfMyType.MethodName(); But you can't use Intellisense because dynamic types are typed in runtime,not in compile time.

Intromission answered 12/1, 2016 at 11:4 Comment(0)
J
2
((ISomeInterface)Activator.CreateInstance(Assembly.LoadFile("somePath").GetTypes()[0])).SomeInterfaceMethod();
Jerrilyn answered 21/1, 2009 at 14:27 Comment(0)
P
2

Depending how intrinsic this kind of functionality is to your project, you might want to consider something like MEF which will take care of the loading and tying together of components for you.

Pacorro answered 21/1, 2009 at 14:30 Comment(0)
D
2

You can load an assembly using *Assembly.Load** methods. Using Activator.CreateInstance you can create new instances of the type you want. Keep in mind that you have to use the full type name of the class you want to load (for example Namespace.SubNamespace.ClassName). Using the method InvokeMember of the Type class you can invoke methods on the type.

Also, take into account that once loaded, an assembly cannot be unloaded until the whole AppDomain is unloaded too (this is basically a memory leak).

Danuloff answered 21/1, 2009 at 14:33 Comment(0)
B
1

Yes, it is, you will want to use the static Load method on the Assembly class, and then call then call the CreateInstance method on the Assembly instance returned to you from the call to Load.

Also, you can call one of the other static methods starting with "Load" on the Assembly class, depending on your needs.

Bootlace answered 21/1, 2009 at 14:26 Comment(0)
K
0

You can do this things on this way:

using System.Reflection;

Assembly MyDALL = Assembly.Load("DALL"); //DALL name of your assembly
Type MyLoadClass = MyDALL.GetType("DALL.LoadClass"); // name of your class
 object  obj = Activator.CreateInstance(MyLoadClass);
Ked answered 21/1, 2009 at 14:20 Comment(0)
R
0

I'm using .net5 (.net core 5). What I need to do is:

    static void Main()
    {
        //...

        AppDomain.CurrentDomain.AssemblyResolve += CciBaseResolveEventHandler;

        Application.Run(new FormMain());
    }

    private static Assembly CciBaseResolveEventHandler(object sender, ResolveEventArgs args)
    {
        return Assembly.LoadFile($@"{Directory.GetCurrentDirectory()}\{nameof(CciBase)}.dll");
    }
  1. Change "CciBase" to your dll name.
  2. Make sure the dll is in the same same folder with the exe.
  3. Do it before the main process starts (Application.Run()).
Raddled answered 24/7, 2021 at 13:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.