在C#中运行时加载DLL

dan*_*oks 76 c# reflection dll

我试图找出如何在C#应用程序中运行时导入和使用.dll.使用Assembly.LoadFile()我设法让我的程序加载dll(这部分肯定是有效的,因为我能够获得带有ToString()的类的名称),但是我无法使用'输出'我的控制台应用程序内的方法.我正在编译.dll然后将其移动到我的控制台项目中.CreateInstance之间是否有额外的步骤,然后能够使用这些方法?

这是我的DLL中的类:

namespace DLL
{
    using System;

    public class Class1
    {
        public void Output(string s)
        {
            Console.WriteLine(s);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我想要加载DLL的应用程序

namespace ConsoleApplication1
{
    using System;
    using System.Reflection;

    class Program
    {
        static void Main(string[] args)
        {
            var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");

            foreach(Type type in DLL.GetExportedTypes())
            {
                var c = Activator.CreateInstance(type);
                c.Output(@"Hello");
            }

            Console.ReadLine();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Dar*_*con 105

成员必须在编译时可以解析才能直接从C#调用.否则,您必须使用反射或动态对象.

反射

namespace ConsoleApplication1
{
    using System;
    using System.Reflection;

    class Program
    {
        static void Main(string[] args)
        {
            var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");

            foreach(Type type in DLL.GetExportedTypes())
            {
                var c = Activator.CreateInstance(type);
                type.InvokeMember("Output", BindingFlags.InvokeMethod, null, c, new object[] {@"Hello"});
            }

            Console.ReadLine();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

动态(.NET 4.0)

namespace ConsoleApplication1
{
    using System;
    using System.Reflection;

    class Program
    {
        static void Main(string[] args)
        {
            var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");

            foreach(Type type in DLL.GetExportedTypes())
            {
                dynamic c = Activator.CreateInstance(type);
                c.Output(@"Hello");
            }

            Console.ReadLine();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这就是为什么经常使用接口,你可以进行特征检测,例如`IDog dog = someInstance作为IDog;`并测试它是否为空.将您的接口放在客户端共享的公共DLL中,任何动态加载的插件都必须实现该接口.这将允许您针对IDog接口编写客户端代码,并在编译时进行智能感知+强类型检查,而不是使用动态. (16认同)
  • 请注意,这会尝试在程序集中的每个类型上调用`Output`,这可能会在找到"right"类之前抛出... (7认同)
  • @Tarek.Mh:这将需要对 Class1 的编译时依赖。那时你可以只使用`new Class1()`。询问者明确指定了运行时依赖项。`dynamic` 允许程序根本不需要对 `Class1` 的编译时依赖。 (2认同)

Ree*_*sey 34

现在,您正在创建程序集中定义每种类型的实例.您只需创建一个实例Class1即可调用该方法:

class Program
{
    static void Main(string[] args)
    {
        var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");

        var theType = DLL.GetType("DLL.Class1");
        var c = Activator.CreateInstance(theType);
        var method = theType.GetMethod("Output");
        method.Invoke(c, new object[]{@"Hello"});

        Console.ReadLine();
    }
}
Run Code Online (Sandbox Code Playgroud)


Alb*_*rto 13

您需要创建一个公开该Output方法的类型的实例:

static void Main(string[] args)
    {
        var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");

        var class1Type = DLL.GetType("DLL.Class1");

        //Now you can use reflection or dynamic to call the method. I will show you the dynamic way

        dynamic c = Activator.CreateInstance(class1Type);
        c.Output(@"Hello");

        Console.ReadLine();
     }
Run Code Online (Sandbox Code Playgroud)