我可以在运行时加载.NET程序集并实例化只知道名称的类型吗?

时间:2009-01-21 14:20:06

标签: c# assemblies

如果我只有DLL名称和类名,是否可以在运行时实例化对象,而无需在项目中添加对程序集的引用?该类实现了一个接口,因此一旦我实例化该类,我就会将它转换为接口。

大会名称:

  

library.dll

输入姓名:

  

Company.Project.Classname


编辑:我没有DLL的绝对路径,因此Assembly.LoadFile无效。 DLL可能位于应用程序root,system32中,甚至可能已加载到GAC中。

14 个答案:

答案 0 :(得分:215)

是。您需要使用Assembly.LoadFrom将程序集加载到内存中,然后可以使用Activator.CreateInstance创建首选类型的实例。您需要先使用反射查看类型。这是一个简单的例子:

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

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

object instanceOfMyType = Activator.CreateInstance(type);

更新

如果您有汇编文件名和类型名称,则可以使用Activator.CreateInstance(assemblyName, typeName)要求.NET类型解析将其解析为类型。您可以使用try / catch包装它,这样如果它失败,您可以搜索目录,您可以专门存储其他可能无法搜索的程序集。这将使用前面的方法。

答案 1 :(得分:34)

考虑不同Load*方法的局限性。来自MSDN文档...

  

LoadFile不会像LoadFrom方法那样使用加载路径将文件加载到LoadFrom上下文中,不会解析依赖关系

有关加载上下文的更多信息,请参阅LoadFrom文档。

答案 2 :(得分:18)

Activator.CreateInstance应该有用。

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

注意:类型名称必须是完全限定类型。

示例:

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

foreach (object obj in aray)
{
    Console.WriteLine(obj);
}

答案 3 :(得分:6)

我发现这个问题和一些答案非常有用,但是我确实遇到了路径问题,因此这个答案将涵盖通过查找bin目录路径来加载库。

第一个解决方案:

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);

第二个解决方案

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");

您可以对接口使用相同的原则(您将创建一个类但是转换为接口),例如:

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

此示例适用于Web应用程序,但类似可用于桌面应用程序,只有路径以不同方式解析,例如

Path.GetDirectoryName(Application.ExecutablePath)

答案 4 :(得分:3)

很容易。

来自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);
}

这是参考链接

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

答案 5 :(得分:3)

从Framework v4.5开始,您可以使用 Activator.CreateInstanceFrom()轻松实例化程序集中的类。 以下示例显示了如何使用它以及如何调用传递参数和获取返回值的方法。

    // 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" } ));

答案 6 :(得分:2)

是。我现在没有任何个人可用的例子。当我找到一些时,我会发布。基本上你会使用反射加载组件,然后拉出你需要的任何类型。

与此同时,这个链接应该让你开始:

Using reflection to load unreferenced assemblies at runtime

答案 7 :(得分:2)

((ISomeInterface)Activator.CreateInstance(Assembly.LoadFile("somePath").GetTypes()[0])).SomeInterfaceMethod();

答案 8 :(得分:2)

根据这种功能对您的项目的内在性,您可能需要考虑MEF之类的内容,它将负责为您加载和组合组件。

答案 9 :(得分:2)

您可以使用* Assembly.Load **方法加载程序集。使用 Activator.CreateInstance ,您可以创建所需类型的新实例。请记住,您必须使用要加载的类的完整类型名称(例如 Namespace.SubNamespace.ClassName )。使用 Type 类的方法 InvokeMember ,您可以调用该类型的方法。

另外,考虑到一旦加载,在卸载整个AppDomain之前无法卸载程序集(这基本上是内存泄漏)。

答案 10 :(得分:2)

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

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

dynamic instanceOfMyType = Activator.CreateInstance(type);

因此,通过这种方式,您可以使用函数而不是获取methodinfo,然后调用它。您将使用此instanceOfMyType.MethodName(); 但是你不能使用Intellisense,因为动态类型是在运行时输入的,而不是在编译时输入的。

答案 11 :(得分:1)

是的,你会想要在Assembly类上使用静态Load方法,然后调用然后调用从调用Load返回给你的Assembly实例上的CreateInstance方法。

此外,您可以根据需要调用Assembly类中以“Load”开头的其他静态方法之一。

答案 12 :(得分:0)

你可以这样做:

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);

答案 13 :(得分:0)

我使用的是 .net5(.net core 5)。我需要做的是:

    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. 将“CciBase”更改为您的 dll 名称。
  2. 确保 dll 与 exe 位于同一文件夹中。
  3. 在主进程启动之前执行此操作 (Application.Run())。