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

Meg*_*yte 175 c# assemblies

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

大会名称:

library.dll

类型名称:

Company.Project.Classname


编辑:我没有DLL的绝对路径,所以Assembly.LoadFile不会工作.DLL可能位于应用程序根目录,system32中,甚至可能已加载到GAC中.

Jef*_*tes 218

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

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

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

object instanceOfMyType = Activator.CreateInstance(type);
Run Code Online (Sandbox Code Playgroud)

更新

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

  • 这有助于......将其标记为已接受的答案? (14认同)
  • 我没有dll的绝对路径,所以assemlby.LoadFile等.不工作,还有其他想法吗? (2认同)
  • @MegaByte:LoadFrom与LoadFile不同。它将解析您的依赖关系,并且应从已知路径(GAC,exe目录等)解析DLL名称。有关更多信息,请参见MSDN。 (2认同)

Ant*_*ean 35

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

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

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

  • 很好地抓住了这里的差异,谢谢! (2认同)

tva*_*son 18

Activator.CreateInstance应该工作.

IFace object = (IFace)Activator.CreateInstance( "AssemblyName",
                                                "TypeName" )
                               .Unwrap();
Run Code Online (Sandbox Code Playgroud)

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

例:

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

foreach (object obj in aray)
{
    Console.WriteLine(obj);
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意:“TypeName”必须是完全限定的。我必须这样调用它: `Activator.CreateInstance("MyAssembly","MyAssembly.TypeName")` 并且返回一个 `ObjectHandle`。要深入了解您的界面,您需要执行“ObjectHandle.UnWrap()” (2认同)

Sof*_*ija 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);
Run Code Online (Sandbox Code Playgroud)

二解决方案

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");
Run Code Online (Sandbox Code Playgroud)

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

(Company.Project.Interfacename) instance = (Company.Project.Interfacename) assembly.CreateInstance("Company.Project.Classname");
Run Code Online (Sandbox Code Playgroud)

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

Path.GetDirectoryName(Application.ExecutablePath)
Run Code Online (Sandbox Code Playgroud)


小智 6

这很简单。

来自 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);
}
Run Code Online (Sandbox Code Playgroud)

这是一个参考链接

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


小智 5

从 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" } ));
Run Code Online (Sandbox Code Playgroud)