C#用dynamic一行代码实现反射操作

Posted .NET100

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#用dynamic一行代码实现反射操作相关的知识,希望对你有一定的参考价值。

dynamic简介

dynamic是.NET Framework4.0的新特性。dynamic的出现让C#具有了弱语言类型的特性。编译器在编译的时候不再对类型进行检查,编译时默认dynamic对象支持你想要的任何特性。

dynamic简化反射实现

使用dynamic来简化反射实现是一种比较常见的编程技巧,它可以减少代码的复杂性并提高可读性。下面是一个使用dynamic来简化反射实现的示例:

// 定义一个类
public class Person

    public string Name  get; set; 
    public int Age  get; set; 
    public string Gender  get; set; 

// 创建一个对象并设定属性值
var person = new Person

    Name = "刘备",
    Age = 30,
    Gender = "男"
;

// 使用反射获取属性值
var type = person.GetType();
var properties = type.GetProperties();
foreach (var property in properties)

    var value = property.GetValue(person);
    Console.WriteLine($"property.Name:value");


// 使用dynamic来简化反射实现
dynamic dynamicPerson = person;
Console.WriteLine($"Name:dynamicPerson.Name, Age:dynamicPerson.Age, Gender:dynamicPerson.Gender");
 //欢迎公众号:DOTNET开发跳槽,领取海量面试题

可以看到,使用dynamic来简化反射实现可以将代码变得更加简洁易读,同时也可以避免一些繁琐的反射操作。使用dynamic可能会带来一些性能上的损失,应该根据具体情况进行选择。具体会不会,下面实验一下。

dynamic与反射的性能对比

这里首先新建一个类和一个两数相加的方法,然后分别使用反射和dynamic来调用这个类的方法,并循环数次,来对比它们的性能。代码如下:

 #region 反射和dynamic的对比
 int times = 1000000;
 DynamicTest reflectTest = new DynamicTest();
 var addMethod = typeof(DynamicTest).GetMethod("Add");
 Stopwatch watchl = Stopwatch.StartNew();
 for (var i = 0;i< times; i++)
  addMethod.Invoke(reflectTest, new object[]  1, 2 ); 
 Console.WriteLine($"反射耗时:watchl.ElapsedMilliseconds毫秒"); 
  dynamic dynamicTest = new DynamicTest();
 Stopwatch watch2 = Stopwatch.StartNew();
 for (int i =0;i< times; i++)
      dynamicTest.Add(1,2);
 Console.WriteLine($"dynamic耗时:watch2.ElapsedMilliseconds 毫秒");
 #endregion
 //测试的类
public class DynamicTest

    public string Nameget; set; 
    public int Add(int a, int b)
    
         return a + b;
    

  //欢迎公众号:DOTNET开发跳槽,领取海量面试题

100万次的效果:

1万次的效果:

可见100万次循环的效果dynamic要好点,1万次反射耗时小于dynamic。为了效果,所以每一次实验运行两次。

结语

由上可以看出dynamic的确可以简化反射,让代码更加简洁,可读性更强。但是从对比来看,dynamic在低数量调用的使用上性能要比反射弱太多,比较大的数量调用来说它们不相上下。建议如果你的代码对性能要求不太高的情况下,可以使用dynamic来简化反射。

参考:微软官方文档,《改善C#程序的157个建议》

来源公众号:DotNet开发跳槽

C# 反射类Assembly用法举例

概述

     程序运行时,通过反射可以得到其它程序集或者自己程序集代码的各种信息,包括类、函数、变量等来实例化它们,执行它们,操作它们,实际上就是获取程序在内存中的映像,然后基于这个映像进行各种操作。

Assembly介绍

Assembly类即程序集类,用来加载其他程序集,加载后可以用Type来使用其他程序集中的信息,如果想要使用其它程序集中的内容,需要先加载程序集。

加载程序集的三种方法:

①、一般用来加载同一文件下的其他程序集

Assembly assembly = Assembly.Load(“AssemblyName”);

②、一般用来加载不再同一文件下的其他程序集

Assembly assembly = Assembly.LoadFrom(“包含程序集清单的文件的名称或路径”);

Assembly assembly = Assembly.LoadFile(“要加载的文件的完全限定路径”);

使用方法:

Assembly asm = Assembly.LoadFrom("Demo.dll");//需要加后缀,可以指定路径,如:Assembly.LoadFrom(@"C:\\Users\\majm\\source\\repos\\ConsoleApp29\\bin\\Debug\\TestDll.dll");

Assembly asm = Assembly.Load("Demo");//无需加后缀,不可以指定路径,

  1. 使用Load可以加载当前程序bin目录行下的程序集或者系统程序集

定义数据模型:创建类库并生成dll

namespace TestDll

    public class Person
    
        public Person()
        
            Name = "zls";
            Age = 18;
            id = 20;
        


        public Person(string name, int age)
        
            Name = name;
            Age = age;
            id = 21;
        


        public string Name  get; set; 
        public int Age  get; set; 


        public int id;


        public int Score(int a, int b)
        
            return a + b;
        
    

第一步:首先加载一个指定程序集:

Assembly assembly = Assembly.LoadFrom(@"C:\\Users\\majm\\source\\repos\\ConsoleApp29\\bin\\Debug\\TestDll.dll");
            Type[] types = assembly.GetTypes();
            for (int i = 0; i < types.Length; i++)
            
                Console.WriteLine(types[i]);
            

运行结果:

第二步:加载程序集中类对象:并调用方法传入参数

Type c1 = types[0];
            object obj = Activator.CreateInstance(c1);
            //调用Class1类中的Speak方法
            MethodInfo speak = c1.GetMethod("Score");
            object[] o = new Object[2] 12,13 ;
            var result = speak.Invoke(obj, o);
            Console.WriteLine(result);

运行结果:25

这里还可以这样如下去创建实例:

Type c1 = types[0];
            Assembly asm = Assembly.GetAssembly(c1);
            Person person = (Person)asm.CreateInstance("TestDll.Person", true);//true:不区分大小写


            //调用Person1类中的Score方法
            MethodInfo speak = c1.GetMethod("Score");
            object[] o = new Object[2] 12,13 ;
            var result = speak.Invoke(person, o);
            Console.WriteLine(result);

一样的效果,如果是当前程序集,可以GetExecutingAssembly获取程序集

Assembly asm = Assembly.GetExecutingAssembly();

以上是关于C#用dynamic一行代码实现反射操作的主要内容,如果未能解决你的问题,请参考以下文章

C#用反射实现两个类的对象之间相同属性的值的复制

在VS里面用C#实现对Excel表的操作

编写高质量代码改善C#程序的157个建议

Dynamics 365中使用JavaScript和C#调用操作示例

Json.net实现方便的Json转C#(dynamic动态类型)对象

Json.net实现方便的Json转C#(dynamic动态类型)对象