前言:
- 反射提高了程序的灵活性和扩展性。
- 降低耦合性,提高自适应能力。
- 它允许程序创建和控制任何类的对象,无需提前硬编码目标类。
一、项目结构
创建项目的语句如下:
> mkdir ReflectionFolder
> cd .\ReflectionFolder\
> dotnet new classlib -n ReflectionTest.Abstractions
> dotnet new classlib -n ReflectionTest
> dotnet new sln -n ReflectionFolder
> dotnet sln add .\ConsoleApp\ConsoleApp.csproj
> dotnet sln add .\ReflectionTest\ReflectionTest.csproj
> dotnet sln add .\ReflectionTest.Abstractions\ReflectionTest.Abstractions.csproj
> cd .\ReflectionTest\
> dotnet add reference ..\ReflectionTest.Abstractions\ReflectionTest.Abstractions.csproj
> cd ..
> cd .\ConsoleApp\
> dotnet add reference ..\ReflectionTest\ReflectionTest.csproj
然后将解决方案打开。
在 ReflectionTest.Abstractions
项目中创建 ITestClass.cs
和 ITestGenericClass.cs
两个文件:
#region [ITestClass.cs]
namespace ReflectionTest.Abstractions
{
public interface ITestClass
{
void TestMethod();
void TestMethodParam(int param);
void TestFunction();
void TestFunction(int param1);
void TestFunction(int param1, string param2);
}
}
#endregion
#region [IReflectionTest.cs]
namespace ReflectionTest.Abstractions
{
public interface ITestGenericClass<T1, T2>
{
void TestFunction<T3>(T1 param1, T2 param2, T3 param3);
int Id { get; set; }
string Name { get; set; }
}
}
#endregion
在 ReflectionTest
项目中创建 TestClass.cs
和 TestGenericClass.cs
两个文件:
#region [TestClass.cs]
namespace ReflectionTest
{
public class TestClass : ITestClass
{
public TestClass()
{
Console.WriteLine("ctor 无参数");
}
public TestClass(int param1)
{
Console.WriteLine($"ctor 一个参数 {{ param1:{param1} }}");
}
public TestClass(int param1, string param2)
{
Console.WriteLine($"ctor 两个参数 {{ param1:{param1}, param2:{param2} }}");
}
public void TestMethod()
{
Console.WriteLine("method 无参方法");
}
public void TestMethodParam(int param)
{
Console.WriteLine($"method 一个参数 {{ param:{param} }}");
}
public static void TestStaticMethod(int param)
{
Console.WriteLine("method 静态无参方法");
}
public void TestFunction()
{
Console.WriteLine("function 无参方法");
}
public void TestFunction(int param1)
{
Console.WriteLine($"function 一个参数 {{ param1:{param1} }}");
}
public void TestFunction(int param1, string param2)
{
Console.WriteLine($"ctor 两个参数 {{ param1:{param1}, param2:{param2} }}");
}
private void TestPrivateMethod(int param1)
{
Console.WriteLine($"function 一个无参私有方法 {{ param1:{param1} }}");
}
}
}
#endregion
#region [TestGenericClass.cs]
namespace ReflectionTest
{
public class TestGenericClass<T1, T2> : ITestGenericClass<T1, T2>
{
private TestGenericClass()
{
Console.WriteLine("ctor 无参数");
}
public void TestFunction<T3>(T1 param1, T2 param2, T3 param3)
{
Console.WriteLine($"ctor 三个参数 {{ param1:{param1}, param2:{param2}, param3:{param3} }}");
}
public int Id { get; set; }
public string Name { get; set; }
public string Description;
}
}
#endregion
二、创建对象并调用方法
在控制台应用程序中进行测试
- 获取类型
Assembly reflectionTestAssembly = Assembly.Load("ReflectionTest");
Type testClassType = reflectionTestAssembly.GetType("ReflectionTest.TestClass");
- 创建对象 (构造函数重载)
var testClass1 = Activator.CreateInstance(testClassType) as ITestClass;
var testClass2 = Activator.CreateInstance(testClassType, new object[] { 123 }) as ITestClass;
var testClass3 = Activator.CreateInstance(testClassType, new object[] { 123, "Upgrader" }) as ITestClass;
- 调用方法 (无参非重载)
var testMethod = testClassType.GetMethod("TestMethod");
testMethod.Invoke(testClass1, null);
- 调用方法 (一个参数非重载)
var testMethodParam = testClassType.GetMethod("TestMethodParam");
testMethodParam.Invoke(testClass1, new object[] { 123 });
- 调用方法 (静态方法)
var testStaticMethod = testClassType.GetMethod("TestStaticMethod");
testStaticMethod.Invoke(testClass1, new object[] { 123 });
testStaticMethod.Invoke(null, new object[] { 123 });
- 调用方法 (重载无参)
var testFunction1 = testClassType.GetMethod("TestFunction", new Type[] { });
testFunction1.Invoke(testClass1, null);
- 调用方法 (重载有参)
var testFunction2 = testClassType.GetMethod("TestFunction", new Type[] { typeof(int) });
testFunction2.Invoke(testClass1, new object[] { 123 });
- 调用方法 (重载有参)
var testFunction3 = testClassType.GetMethod("TestFunction", new Type[] { typeof(int), typeof(string) });
testFunction3.Invoke(testClass1, new object[] { 123, "Upgrader" });
- 调用私有方法
var testPrivateMethod = testClassType.GetMethod("TestPrivateMethod", BindingFlags.Instance | BindingFlags.NonPublic);
testPrivateMethod.Invoke(testClass1, new object[] { 123 });
- 获取类型 (泛型)
var testGenericClassType = reflectionTestAssembly.GetType("ReflectionTest.TestGenericClass`2");
var makeGenericType = testGenericClassType.MakeGenericType(new Type[] { typeof(int), typeof(string) });
- 访问私有构造函数创建对象
var testGenericClass = Activator.CreateInstance(makeGenericType, true);
- 调用泛型方法
var testFunction = makeGenericType.GetMethod("TestFunction");
var makeTestFunction = testFunction.MakeGenericMethod(new Type[] { typeof(DateTime) });
makeTestFunction.Invoke(testGenericClass, new object[] { 123, "Upgrader", DateTime.Now });
三、创建对象并修改属性和字段
var testGenericClass2 = Activator.CreateInstance(makeGenericType, true) as TestGenericClass<int, string>;
Type type = testGenericClass2.GetType();
- 遍历属性
foreach (var prop in type.GetProperties())
{
if (prop.Name.Equals("Id"))
prop.SetValue(testGenericClass2, 321);
else if (prop.Name.Equals("Name"))
prop.SetValue(testGenericClass2, "Achovin");
Console.WriteLine($"{{ typeName:{type.Name}, Name:{prop.Name}, Value:{prop.GetValue(testGenericClass2)} }}");
}
- 便利字段
foreach (var field in type.GetFields())
{
if (field.Name.Equals("Description"))
field.SetValue(testGenericClass2, "Description");
Console.WriteLine($"{{ typeName:{type.Name}, Name:{field.Name}, Value:{field.GetValue(testGenericClass2)} }}");
}