简体   繁体   English

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

[英]Can I load a .NET assembly at runtime and instantiate a type knowing only the name?

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?如果我只有 DLL 名称和类名,而不在项目中添加对程序集的引用,是否可以在运行时实例化对象? 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.编辑:我没有 DLL 的绝对路径,所以Assembly.LoadFile不起作用。 The DLL might be in the application root, system32, or even loaded in the GAC. DLL 可能位于应用程序根目录、system32 中,甚至可能加载到 GAC 中。

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.您需要使用Assembly.LoadFrom将程序集加载到内存中,然后您可以使用Activator.CreateInstance创建您首选类型的实例。 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.当您有程序集文件名和类型名时,您可以使用Activator.CreateInstance(assemblyName, typeName)要求 .NET 类型解析将其解析为类型。 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.您可以使用 try/catch 对其进行包装,以便在失败时执行目录搜索,您可以在其中专门存储其他程序集,否则可能无法搜索到这些程序集。 This would use the preceding method at that point.这将在那时使用前面的方法。

Consider the limitations of the different Load* methods.考虑不同Load*方法的局限性。 From the MSDN docs...MSDN文档...

LoadFile does not load files into the LoadFrom context, and does not resolve dependencies using the load path, as the LoadFrom method does. LoadFile 不会将文件加载到 LoadFrom 上下文中,并且不会像 LoadFrom 方法那样使用加载路径解析依赖项

More information on Load Contexts can be found in the LoadFrom docs.可以在LoadFrom文档中找到有关加载上下文的更多信息。

Activator.CreateInstance ought to work. Activator.CreateInstance应该可以工作。

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

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.我发现这个问题和一些答案非常有用,但是我确实遇到了路径问题,所以这个答案将通过查找 bin 目录路径来涵盖加载库。

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此示例适用于 Web 应用程序,但类似的可用于桌面应用程序,只是路径以不同的方式解析,例如

Path.GetDirectoryName(Application.ExecutablePath)

It's Easy.这简单。

Example from MSDN:来自 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 https://msdn.microsoft.com/en-us/library/25y1ya39.aspx

Starting from Framework v4.5 you can use Activator.CreateInstanceFrom() to easily instantiate classes within assemblies.从 Framework v4.5 开始,您可以使用Activator.CreateInstanceFrom()轻松实例化程序集中的类。 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" } ));
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();所以通过这种方式你可以使用函数而不是获取方法信息,然后调用它。你会像这样 instanceOfMyType.MethodName(); But you can't use Intellisense because dynamic types are typed in runtime,not in compile time.但是您不能使用 Intellisense,因为动态类型是在运行时而不是在编译时输入的。

Yes.是的。 I don't have any examples that I've done personally available right now.我现在没有任何我亲自做过的例子。 I'll post later when I find some.等我找到了以后再发。 Basically you'll use reflection to load the assembly and then to pull whatever types you need for it.基本上,您将使用反射来加载程序集,然后提取您需要的任何类型。

In the meantime, this link should get you started:与此同时,这个链接应该让你开始:

Using reflection to load unreferenced assemblies at runtime使用反射在运行时加载未引用的程序集

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

根据此类功能对您的项目的固有程度,您可能需要考虑诸如MEF 之类的东西,它将为您处理组件的加载和绑定。

You can load an assembly using *Assembly.Load** methods.您可以使用 *Assembly.Load** 方法加载程序集。 Using Activator.CreateInstance you can create new instances of the type you want.使用Activator.CreateInstance您可以创建所需类型的新实例。 Keep in mind that you have to use the full type name of the class you want to load (for example Namespace.SubNamespace.ClassName ).请记住,您必须使用要加载的类的完整类型名称(例如Namespace.SubNamespace.ClassName )。 Using the method InvokeMember of the Type class you can invoke methods on the type.使用Type类的InvokeMember方法,您可以调用该类型的方法。

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).另外,请考虑到一旦加载,在整个 AppDomain 也卸载之前无法卸载程序集(这基本上是内存泄漏)。

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.是的,是的,您将希望在Assembly 类上使用静态Load 方法,然后在调用Load 时返回给您的Assembly 实例上调用然后调用CreateInstance 方法。

Also, you can call one of the other static methods starting with "Load" on the Assembly class, depending on your needs.此外,您可以根据需要在 Assembly 类上调用以“Load”开头的其他静态方法之一。

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

I'm using .net5 (.net core 5).我正在使用 .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.将“CciBase”更改为您的 dll 名称。
  2. Make sure the dll is in the same same folder with the exe.确保 dll 与 exe 位于同一文件夹中。
  3. Do it before the main process starts (Application.Run()).在主进程启动之前执行(Application.Run())。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我可以在不知道dll文件名的情况下加载程序集,其中我只知道命名空间名称 - Can I load an Assembly without knowing the dll filename, where I only know the namespace name 在运行时加载程序集 .NET 6 - Load Assembly at Runtime .NET 6 我可以在不知道路径的情况下在运行时加载(通常是引用的)dll吗? - Can I load (usually referenced) dll at runtime without knowing the path? 无论类型如何,我都可以在运行时为 OrderBy 实例化 IComparer 类吗? - Can I Instantiate an IComparer class at runtime for OrderBy regardless of type? 在运行时更改.Net程序集名称 - Changing .Net assembly name at runtime 除非我首先在该程序集中实例化一个类,否则无法对引用的程序集进行Assembly.Load(String)。 怎么解决? - Can't do Assembly.Load(String) with a referenced assembly unless I instantiate a class within that assembly first. How to solve? 如何仅使用表单名称实例化并显示表单? - How can I instantiate and display a Form using only the name of the Form? 在运行时知道类型变量 - knowing type variable at runtime 如何仅在运行时向知道对象名称的动态对象添加属性 - How to add a propery to a dynamic object knowing the name of the column only at runtime WinStore / WinPhone-如何获取在设计时无法引用的程序集的运行时程序集类型 - WinStore/WinPhone - how can I get runtime Assembly type for assembly I cannot reference at design time
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM