C#强化系列文章五:动态代码的使用(反射和动态生成类)
在软件开发尤其是框架和底层开发时,为了更灵活的控制代码,常常需要进行一些动态的操作。比如根据用户的输入等动态的调用类中的方法或者根据数据库表结构、用户要求动态的生成一些类,然后再动态的调用类中的方法。当然使用这些方式时会对性能有一点影响,具体使用过程中可以根据实际情况来定,不过一般的B/S开发中主要的瓶颈还是在数据库操作和网速方面,这点影响应该可以忽略的
下面我就从这两个方面来说说动态代码的使用:
一、反射的使用
可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。
需要使用的命名空间:System.Reflection
反射的作用很多,下面的例子主要是看一下怎么动态的调用类中的方法。
例子类
这个例子中提供了三个方法和一个属性,下面的代码来动态的调用它们:
string strText = "abcd";

BindingFlags flags = (BindingFlags.NonPublic | BindingFlags.Public |
BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);

Type t = typeof(ReflTest1);
MethodInfo[] mi = t.GetMethods(flags);
Object obj = Activator.CreateInstance(t);

foreach (MethodInfo m in mi)
{
if (m.Name.StartsWith("Write"))
{
m.Invoke(obj, new object[] { strText });
}
}

MethodInfo mMy = t.GetMethod("MyWrite");
if (mMy != null)
{
mMy.Invoke(obj, new object[] { strText });
}
BindingFlags用来设置要取得哪些类型的方法,然后我们就可以取得这些方法来动态的调用。(当然为了可以循环的调用方法,在方法的命名方面可以自己指定一个规则)
二、动态生成类
我们可以在程序运行过程中调用.NET中提供的编译类,动态的将一段string编译成一个类,然后再通过反射来调用它
需要使用的命名空间:System.CodeDom System.CodeDom.Compiler Microsoft.CSharp System.Reflection
动态创建、编译类的代码如下:
public static Assembly NewAssembly()
{
//创建编译器实例。
provider = new CSharpCodeProvider();
//设置编译参数。
paras = new CompilerParameters();
paras.GenerateExecutable = false;
paras.GenerateInMemory = true;

//创建动态代码。
StringBuilder classSource = new StringBuilder();
classSource.Append("public class DynamicClass \n");
classSource.Append("{\n");

//创建属性。
classSource.Append(propertyString("aaa"));
classSource.Append(propertyString("bbb"));
classSource.Append(propertyString("ccc"));

classSource.Append("}");

System.Diagnostics.Debug.WriteLine(classSource.ToString());

//编译代码。
CompilerResults result = provider.CompileAssemblyFromSource(paras, classSource.ToString());

//获取编译后的程序集。
Assembly assembly = result.CompiledAssembly;

return assembly;
}

private static string propertyString(string propertyName)
{
StringBuilder sbProperty = new StringBuilder();
sbProperty.Append(" private int _" + propertyName + " = 0;\n");
sbProperty.Append(" public int " + "" + propertyName + "\n");
sbProperty.Append(" {\n");
sbProperty.Append(" get{ return _" + propertyName + ";} \n");
sbProperty.Append(" set{ _" + propertyName + " = value; }\n");
sbProperty.Append(" }");
return sbProperty.ToString();
}
propertyString方法就是用来拼写字符串的
整个代码比较简单,主要步骤就是:1、拼写类的字符串 2、调用CSharpCodeProvider类进行编译得到程序集(assembly)
接下来就可以利用之前反射的方法来动态调用这个类中的属性了:
Assembly assembly = NewAssembly();

object Class1 = assembly.CreateInstance("DynamicClass");
ReflectionSetProperty(Class1, "aaa", 10);
ReflectionGetProperty(Class1, "aaa");

object Class2 = assembly.CreateInstance("DynamicClass");
ReflectionSetProperty(Class1, "bbb", 20);
ReflectionGetProperty(Class1, "bbb");
DynamicClass是我动态类的类名,aaa和bbb是其中的属性
ReflectionSetProperty和ReflectionGetProperty代码如下:
给属性赋值
取得属性的值

下面我就从这两个方面来说说动态代码的使用:
一、反射的使用
可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。
需要使用的命名空间:System.Reflection
反射的作用很多,下面的例子主要是看一下怎么动态的调用类中的方法。
























二、动态生成类
我们可以在程序运行过程中调用.NET中提供的编译类,动态的将一段string编译成一个类,然后再通过反射来调用它
需要使用的命名空间:System.CodeDom System.CodeDom.Compiler Microsoft.CSharp System.Reflection
动态创建、编译类的代码如下:











































整个代码比较简单,主要步骤就是:1、拼写类的字符串 2、调用CSharpCodeProvider类进行编译得到程序集(assembly)
接下来就可以利用之前反射的方法来动态调用这个类中的属性了:









ReflectionSetProperty和ReflectionGetProperty代码如下:


【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?