我学习了动态加载dll如何编程。我在库上有测试类:
public class Class1
{
public int Number { get; set; }
public string GetWorld()
{
return "Hello world!";
}
}
在我的程序代码中动态加载此库和函数TestLibraryMethod从库中返回Class的实例。那怎么写得对呢?
class Program
{
static void Main(string[] args)
{
try
{
var DLL = Assembly.LoadFile(@"C:\TestLibrary.dll");
var reportType = DLL.GetTypes().ToList().Where(t => t.Name == "Class1").Single();
var instance = Activator.CreateInstance(reportType);
Class1 test=(call TestLibraryMethod()?)
Console.WriteLine(test.Number);
Console.WriteLine(test.GetWorld());
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
public static Class1 TestLibraryMethod()
{
Class1 test = new Class1();
test.Number = 5;
return test;
}
}
答案 0 :(得分:0)
由于在流程的编译阶段不知道类型,因此您需要使用反射来访问它。您可以找到introduction to that topic on MSDN。
例如,以您的示例为例,读取属性并调用您将编写此方法的方法:
PropertyInfo NumberProp = reportType.GetProperty("Number");
Console.WriteLine(NumberProp.GetValue(instance));
MethodInfo GetWorldMethod = reportType.GetMethod("GetWorld");
Console.WriteLine(GetWorldMethod.Invoke(instance, null));
以这种方式使用反射并不是很有趣。我宁愿怀疑你最好在主机程序集和动态加载程序集使用的程序集中定义接口。在动态加载的程序集中,您将定义一个实现该类型的类,并提供一个创建并返回新实例的方法。这样,您就可以在编译时绑定到该类型。
答案 1 :(得分:0)
@David所指的是,你通常不会这样做。但是,如果您仍然需要这样的功能,则需要考虑接口(或合同)来完成此任务。
在程序集A中说,您已定义了接口:
public interface IRunnable
{
void Run();
}
在程序集B中,您将具体实现。所以这个程序集引用了A.因此,程序集中的类实现了IRunnable。
在您的前端,即目标程序集(可能是桌面应用程序,Web应用程序或任何应用程序)中,您可以添加对程序集A的引用。程序集B是动态加载的。并且该特定类型的实例就像您在上面所做的那样,并且该实例被赋予IRunnable变量。
因此,在您的情况下,实例化代码将是:
var instance = (IRunnable) Activator.CreateInstance(reportType);
instance.Run();
这是推荐的方法。