使用反射(Reflect)获取DLL文件中的类型并调用方法可以分为以下几个步骤:
1.加载DLL文件:使用Assembly.LoadFrom
方法加载指定DLL文件。
Assembly assembly = Assembly.LoadFrom("MyLibrary.dll");
2.获取类型:使用Assembly.GetType
方法获取指定类型的Type
对象。
Type type = assembly.GetType("MyLibrary.MyClass");
3.创建对象:使用Activator.CreateInstance
方法创建指定类型的实例。
object instance = Activator.CreateInstance(type);
4.调用方法:使用Type.GetMethod
方法获取指定方法的MethodInfo
对象,然后使用MethodInfo.Invoke
方法调用该方法。
MethodInfo method = type.GetMethod("MyMethod");
method.Invoke(instance, null);
创建对象的两种方法:
Activator.CreateInstance方法可以创建任意类型的对象,使用Type.GetConstructor
方法获取到指定的构造函数,然后调用其Invoke
方法来创建对象。
using System;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
Assembly assembly = Assembly.LoadFrom("MyLibrary.dll");
Type type = assembly.GetType("MyLibrary.MyClass");
// 通过 Activator.CreateInstance 方法创建有参对象
object instance1 = Activator.CreateInstance(type, "parameter1");
// 通过构造函数的方式创建有参对象
ConstructorInfo constructor1 = type.GetConstructor(new Type[] { typeof(string) });
object instance2 = constructor1.Invoke(new object[] { "parameter2" });
// 通过 Activator.CreateInstance 方法创建无参对象
object instance3 = Activator.CreateInstance(type);
// 通过构造函数的方式创建无参对象
ConstructorInfo constructor2 = type.GetConstructor(Type.EmptyTypes);
object instance4 = constructor2.Invoke(null);
// 调用有参方法
MethodInfo method1WithParameters = type.GetMethod("MyMethodWithParameters");
method1WithParameters.Invoke(instance1, new object[] { "method1 parameter" });
// 调用无参方法
MethodInfo method2 = type.GetMethod("MyMethod");
method2.Invoke(instance2, null);
// 调用有参方法
method1WithParameters.Invoke(instance3, new object[] { "method1 parameter for instance3" });
// 调用无参方法
method2.Invoke(instance4, null);
}
}
namespace MyLibrary
{
public class MyClass
{
// 有参构造函数
public MyClass(string param)
{
Console.WriteLine("Parameterized constructor called! Parameter: " + param);
}
// 无参构造函数
public MyClass()
{
Console.WriteLine("Default constructor called!");
}
// 有参方法
public void MyMethodWithParameters(string param)
{
Console.WriteLine("Method with parameters called! Parameter: " + param);
}
// 无参方法
public void MyMethod()
{
Console.WriteLine("Method called!");
}
}
}
当我们使用反射实例化对象时,可以根据具体的需求选择适合的方法。
-
Activator.CreateInstance(Type type)
这是一个通用的实例化对象方法,可以创建任意类型的对象。我们只需要将要创建的对象的类型作为参数传递给Activator.CreateInstance
方法即可。返回的是一个object
类型的实例,需要进行类型转换后才能调用具体的成员。优点:
- 简单方便,不需要知道具体的构造函数和参数类型。
- 可以动态地创建对象,适用于在运行时根据条件决定要创建的对象类型的情况。
缺点:
- 使用反射机制,性能上可能会比直接调用构造函数的方式略慢些。
-
Type.GetConstructor(Type[] types).Invoke(object[] parameters)
这种方式通过构造函数来实例化对象。首先,我们需要使用Type.GetConstructor
方法获取到指定的构造函数,然后调用其Invoke
方法来创建对象。在调用Invoke
方法时,我们需要传入一个Type[]
数组作为构造函数的参数类型列表,并传入一个object[]
数组作为构造函数的参数值列表。优点:
- 可以精确地指定要使用的构造函数及其参数。
- 在创建对象时可以传递参数,灵活性更高。
缺点:
- 需要明确知道要使用的构造函数及其参数类型。
- 需要在代码中显式地指定构造函数的参数类型和值。
总结:
- 如果我们需要在运行时动态地创建对象,并且不需要传递构造函数的参数,可以使用
Activator.CreateInstance
方法。 - 如果我们需要精确地指定构造函数以及参数,并且能够灵活地控制对象的创建过程,可以使用
Type.GetConstructor
和Invoke
方法。
需要注意的是,反射机制在性能上可能会比直接调用构造函数的方式略慢,因此在实际开发中应根据具体情况选择合适的方式。
我们创建了一个类库项目,定义了一个类,包含了4个方法,一个带有1个参数,一个带有2个参数,一个没有参数,以及一个私有方法。然后编译生成了dll。接着,我们在另一个项目中读取MyClassLibrary.dll为字节流并加载了该dll,并调用了其中的方法。
namespace MyClassLibrary
{
public class MyClass
{
public void MethodWithOneParam(string message)
{
Console.WriteLine("MethodWithOneParam called with message: " + message);
}
public void MethodWithTwoParams(int num1, int num2)
{
Console.WriteLine("MethodWithTwoParams called with nums: " + num1 + " and " + num2);
}
public void MethodWithoutParam()
{
Console.WriteLine("MethodWithoutParam called");
}
private void PrivateMethod()
{
Console.WriteLine("PrivateMethod called");
}
public void PublicCallPrivateMethod()
{
PrivateMethod();
}
}
}
编译MyClassLibrary项目,生成MyClassLibrary.dll文件。
创建一个新的控制台应用程序项目,命名为MyConsoleApp。
在MyConsoleApp项目中,编写以下代码来加载MyClassLibrary.dll,并调用其中的方法:
using System;
using System.IO;
using System.Reflection;
namespace MyConsoleApp
{
class Program
{
static void Main(string[] args)
{
// 读取MyClassLibrary.dll为字节流
byte[] assemblyBytes = File.ReadAllBytes("MyClassLibrary.dll");
// 加载字节流为程序集
Assembly assembly = Assembly.Load(assemblyBytes);
// 获取MyClass类型
Type myClassType = assembly.GetType("MyClassLibrary.MyClass");
// 创建MyClass实例
object myClassInstance = Activator.CreateInstance(myClassType);
// 调用MethodWithOneParam方法
MethodInfo methodWithOneParam = myClassType.GetMethod("MethodWithOneParam");
methodWithOneParam.Invoke(myClassInstance, new object[] { "Hello from method with one param" });
// 调用MethodWithTwoParams方法
MethodInfo methodWithTwoParams = myClassType.GetMethod("MethodWithTwoParams");
methodWithTwoParams.Invoke(myClassInstance, new object[] { 5, 10 });
// 调用MethodWithoutParam方法
MethodInfo methodWithoutParam = myClassType.GetMethod("MethodWithoutParam");
methodWithoutParam.Invoke(myClassInstance, null);
// 调用PrivateMethod 通过PublicCallPrivateMethod
MethodInfo publicCallPrivateMethod = myClassType.GetMethod("PublicCallPrivateMethod");
publicCallPrivateMethod.Invoke(myClassInstance, null);
}
}
}