当前位置: 代码网 > it编程>编程语言>Asp.net > C#动态生成实体类的5种方法详解与实战演示

C#动态生成实体类的5种方法详解与实战演示

2025年04月24日 Asp.net 我要评论
摘要:本文介绍c#中动态生成实体类的5种实用方法,涵盖t4模板、codedom、roslyn、反射和emit等技术,通过真实代码示例帮助开发者应对不同场景需求。一、应用场景分析动态生成实体类常用于:数

摘要:本文介绍c#中动态生成实体类的5种实用方法,涵盖t4模板、codedom、roslyn、反射和emit等技术,通过真实代码示例帮助开发者应对不同场景需求。

一、应用场景分析

动态生成实体类常用于:

数据库表结构变动时自动同步

动态解析json/xml等异构数据源

减少重复编码工作

运行时动态类型创建

二、实现方案对比

方法易用性灵活性性能适用阶段
t4模板★★★★★★设计时
codedom★★★★★★设计/运行时
roslyn api★★★★★★★运行时
reflection.emit★★★★★★运行时
第三方库★★★★★★★运行时

三、具体实现方法

方法1:使用t4模板生成(设计时)

<#@ template debug="false" hostspecific="true" language="c#" #>
<#@ output extension=".cs" #>
<#
    var classname = "dynamicentity";
    var properties = new dictionary<string, string> 
    {
        {"id", "int"},
        {"name", "string"}
    };
#>
// auto-generated class
public class <#= classname #>
{
<# foreach(var prop in properties) { #>
    public <#= prop.value #> <#= prop.key #> { get; set; }
<# } #>
}

优点:visual studio原生支持

缺点:需要预生成文件

方法2:使用codedom(运行时)

var compileunit = new codecompileunit();
var @namespace = new codenamespace("dynamicentities");
var @class = new codetypedeclaration("person") { isclass = true };
 
@class.members.add(new codememberfield(typeof(int), "_age"));
var property = new codememberproperty()
{
    name = "age",
    type = new codetypereference(typeof(int)),
    attributes = memberattributes.public
};
property.getstatements.add(new codemethodreturnstatement(
    new codefieldreferenceexpression(null, "_age")));
property.setstatements.add(new codeassignstatement(
    new codefieldreferenceexpression(null, "_age"),
    new codepropertysetvaluereferenceexpression()));
    
@class.members.add(property);
var provider = new csharpcodeprovider();
using var writer = new stringwriter();
provider.generatecodefromcompileunit(compileunit, writer, null);
file.writealltext("person.cs", writer.tostring());

适用场景:需要生成完整类文件时

方法3:使用roslyn api(运行时)

var syntaxtree = csharpsyntaxtree.parsetext(@"
using system;
namespace dynamicentities
{
    public class employee
    {
        public string firstname { get; set; }
        public decimal salary { get; set; }
    }
}");
 
var compilation = csharpcompilation.create("dynamicassembly")
    .addreferences(metadatareference.createfromfile(typeof(object).assembly.location))
    .addsyntaxtrees(syntaxtree);
 
using var ms = new memorystream();
var result = compilation.emit(ms);
if (result.success)
{
    var assembly = assembly.load(ms.toarray());
    dynamic obj = activator.createinstance(assembly.gettype("dynamicentities.employee"));
    obj.firstname = "john";
}

优势:支持完整的编译流程

注意:需要安装microsoft.codeanalysis.csharp包

方法4:使用reflection.emit(高性能)

var assemblyname = new assemblyname("dynamicassembly");
var assemblybuilder = assemblybuilder.definedynamicassembly(assemblyname, assemblybuilderaccess.run);
var modulebuilder = assemblybuilder.definedynamicmodule("mainmodule");
var typebuilder = modulebuilder.definetype("product", typeattributes.public);
 
// 添加属性
var fieldbuilder = typebuilder.definefield("_price", typeof(decimal), fieldattributes.private);
var propertybuilder = typebuilder.defineproperty("price", propertyattributes.none, typeof(decimal), null);
 
// 生成get/set方法
var getsetattr = methodattributes.public | methodattributes.specialname;
var getmethod = typebuilder.definemethod("get_price", getsetattr, typeof(decimal), type.emptytypes);
var getil = getmethod.getilgenerator();
getil.emit(opcodes.ldarg_0);
getil.emit(opcodes.ldfld, fieldbuilder);
getil.emit(opcodes.ret);
 
var setmethod = typebuilder.definemethod("set_price", getsetattr, null, new[] { typeof(decimal) });
var setil = setmethod.getilgenerator();
setil.emit(opcodes.ldarg_0);
setil.emit(opcodes.ldarg_1);
setil.emit(opcodes.stfld, fieldbuilder);
setil.emit(opcodes.ret);
 
propertybuilder.setgetmethod(getmethod);
propertybuilder.setsetmethod(setmethod);
 
var dynamictype = typebuilder.createtype();
dynamic obj = activator.createinstance(dynamictype);
obj.price = 99.99m;

特点:最高性能,适合高频使用场景

四、注意事项

动态程序集无法卸载问题

类型冲突处理

调试困难建议添加异常处理

考虑使用缓存机制提升性能

五、方案选型建议

简单场景:选择t4模板

需要动态编译:使用roslyn

高性能需求:优先emit

快速开发:选择第三方库如newtonsoft.json

结语:根据项目需求选择合适方案,建议从t4模板开始熟悉,逐步掌握emit等高级技巧。欢迎在评论区交流实际应用场景!

推荐工具:

linqpad:快速测试动态代码

ilspy:查看生成的il代码

microsoft.codeanalysis:roslyn核心库

到此这篇关于c#动态生成实体类的5种方法详解与实战演示的文章就介绍到这了,更多相关c#动态生成实体类内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com