C# 中的常用的反射方法

1 篇文章 0 订阅
1 篇文章 0 订阅

前言:

  1. 反射提高了程序的灵活性和扩展性。
  2. 降低耦合性,提高自适应能力。
  3. 它允许程序创建和控制任何类的对象,无需提前硬编码目标类。

一、项目结构

创建项目的语句如下:

> 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.csITestGenericClass.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.csTestGenericClass.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)} }}");
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值