我试图找出如何在C#应用程序中运行时导入和使用.dll。使用Assembly.LoadFile()我设法让我的程序加载dll(这部分肯定是有效的,因为我能够获得带有ToString()的类的名称),但是我无法使用'输出'我的控制台应用程序内的方法。我正在编译.dll然后将其移动到我的控制台项目中。 CreateInstance之间是否有额外的步骤,然后才能使用这些方法?
这是我的DLL中的类:
namespace DLL
{
using System;
public class Class1
{
public void Output(string s)
{
Console.WriteLine(s);
}
}
}
这是我想要加载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();
}
}
}
答案 0 :(得分:99)
成员必须在编译时可以解析才能直接从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();
}
}
}
动态(.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();
}
}
}
答案 1 :(得分:33)
现在,您正在创建在程序集中定义的每种类型的实例。您只需创建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();
}
}
答案 2 :(得分:11)
您需要创建一个公开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();
}
答案 3 :(得分:0)
Activator.CreateInstance()
返回一个没有Output方法的对象。
看起来你来自动态编程语言? C#绝对不是那样,而你想要做的事情将很难。
由于您是从特定位置加载特定的dll,可能只是想将其添加为控制台应用程序的参考?
如果您绝对想通过Assembly.Load
加载程序集,则必须通过反思调用c
上的任何成员
像type.GetMethod("Output").Invoke(c, null);
之类的东西应该这样做。
答案 4 :(得分:0)
foreach (var f in Directory.GetFiles(".", "*.dll"))
Assembly.LoadFrom(f);
这将加载可执行文件文件夹中存在的所有DLL。
就我而言,我试图使用Reflection
查找某个类的所有子类,即使在其他DLL中也是如此。这行得通,但是我不确定这是否是最好的方法。
编辑:我对它进行了计时,它似乎只是第一次加载它们。
Stopwatch stopwatch = new Stopwatch();
for (int i = 0; i < 4; i++)
{
stopwatch.Restart();
foreach (var f in Directory.GetFiles(".", "*.dll"))
Assembly.LoadFrom(f);
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
}
输出: 34 0 0 0
因此,为防万一,可以在任何Reflection搜索之前运行该代码。
答案 5 :(得分:-2)
这并不困难。
您可以检查已加载对象的可用功能,如果找到了您要按名称查找的功能,则可以窥探其预期的参数(如果有)。如果它是您尝试查找的呼叫,则使用MethodInfo对象的Invoke方法调用它。
另一种选择是简单地将外部对象构建到接口,并将加载的对象强制转换为该接口。如果成功,请本机调用该函数。
这很简单。