AOT使用经验总结

news/2024/11/6 9:22:45/文章来源:https://www.cnblogs.com/Dotnet9-com/p/18529239

一、引言

站长接触 AOT 已有 3 个月之久,此前在《好消息:NET 9 X86 AOT的突破 - 支持老旧Win7与XP环境》一文中就有所提及。在这段时间里,站长使用 Avalonia 开发的项目也成功完成了 AOT 发布测试。然而,这一过程并非一帆风顺。站长在项目功能完成大半部分才开始进行 AOT 测试,期间遭遇了不少问题,可谓是 “踩坑无数”。为了方便日后回顾,也为了给广大读者提供参考,在此将这段经历进行总结。

.NET AOT是将.NET代码提前编译为本机代码的技术。其优势众多,启动速度快,减少运行时资源占用,还提高安全性。AOT发布后无需再安装.NET运行时等依赖。.NET 8、9 AOT发布后,可在XP、Win7非SP1操作系统下运行。这使得应用部署更便捷,能适应更多老旧系统环境,为开发者拓展了应用场景,在性能提升的同时,也增加了系统兼容性,让.NET应用的开发和部署更具灵活性和广泛性,给用户带来更好的体验。

二、经验之谈

(一)测试策略的重要性

从项目创建伊始,就应养成良好的习惯,即只要添加了新功能或使用了较新的语法,就及时进行 AOT 发布测试。否则,问题积累到后期,解决起来会异常艰难,站长就因前期忽视了这一点,付出了惨痛的代价。无奈的解决方法是重新创建项目,然后逐个还原功能并进行 AOT 测试。经过了一周的加班AOT测试,每个 AOT 发布过程大致如下:

  1. 内网 AOT 发布一次需 2、3 分钟,这段时间只能看看需求文档、技术文章、需求文档、技术文章。。。
  2. 发布完成,运行无效果,体现在双击未出现界面,进程列表没有它,说明程序崩溃了,查看系统应用事件日志,日志中通常会包含异常警告信息。
  3. 依据日志信息检查代码,修改相关 API。
  4. 再次进行 AOT 发布,重复上述 1 - 3 步骤。

经过一周的努力,项目 AOT 后功能测试终于正常,至此收工。

(二)AOT 需要注意的点及解决方法

1. 添加rd.xml

在主工程创建一个XML文件,例如Roots.xml,内容大致如下:

<linker><assembly fullname="CodeWF.Toolbox.Desktop" preserve="All" />
</linker>

需要支持AOT的工程,在该XML中添加一个assembly节点,fullname是程序集名称,CodeWF.Toolbox.Desktop是站长小工具的主工程名,点击查看源码。

在主工程添加ItemGroup节点关联该XML文件:

<ItemGroup><TrimmerRootDescriptor Include="Roots.xml" />
</ItemGroup>

2. Prism支持

站长使用了Prism框架及DryIOC容器,若要支持 AOT,需要添加以下 NuGet 包:

<PackageReference Include="Prism.Avalonia" Version="8.1.97.11073" />
<PackageReference Include="Prism.DryIoc.Avalonia" Version="8.1.97.11073" />

rd.xml需要添加

<assembly fullname="Prism" preserve="All" />
<assembly fullname="DryIoc" preserve="All" />
<assembly fullname="Prism.Avalonia" preserve="All" />
<assembly fullname="Prism.DryIoc.Avalonia" preserve="All" />

3. App.config读写

在.NET Core中使用System.Configuration.ConfigurationManager包操作App.config文件,rd.xml需添加如下内容:

<assembly fullname="System.Configuration.ConfigurationManager" preserve="All" />

使用Assembly.GetEntryAssembly().location失败,目前使用ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)获取的应用程序程序配置,指定路径的方式后续再研究。

4. HttpClient使用

rd.xml添加如下内容:

<assembly fullname="System.Net.Http" preserve="All" />

5. Dapper支持

Dapper的AOT支持需要安装Dapper.AOT包,rd.xml添加如下内容:

<assembly fullname="Dapper" preserve="All" />
<assembly fullname="Dapper.AOT" preserve="All" />

数据库操作的方法需要添加DapperAOT特性,举例如下:

[DapperAot]
public static bool EnsureTableIsCreated()
{try{using var connection = new SqliteConnection(DBConst.DBConnectionString);connection.Open();const string sql = $@"CREATE TABLE IF NOT EXISTS {nameof(JsonPrettifyEntity)}({nameof(JsonPrettifyEntity.IsSortKey)} Bool,{nameof(JsonPrettifyEntity.IndentSize)} INTEGER)";using var command = new SqliteCommand(sql, connection);return command.ExecuteNonQuery() > 0;}catch (Exception ex){return false;}
}

6. System.Text.Json

参考JsonExtensions.cs

序列化

public static bool ToJson<T>(this T obj, out string? json, out string? errorMsg)
{if (obj == null){json = default;errorMsg = "Please provide object";return false;}var options = new JsonSerializerOptions(){WriteIndented = true,Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,TypeInfoResolver = new DefaultJsonTypeInfoResolver()};try{json = JsonSerializer.Serialize(obj, options);errorMsg = default;return true;}catch (Exception ex){json = default;errorMsg = ex.Message;return false;}
}

反序列化

public static bool FromJson<T>(this string? json, out T? obj, out string? errorMsg)
{if (string.IsNullOrWhiteSpace(json)){obj = default;errorMsg = "Please provide json string";return false;}try{var options = new JsonSerializerOptions(){Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,TypeInfoResolver = new DefaultJsonTypeInfoResolver()};obj = JsonSerializer.Deserialize<T>(json!, options);errorMsg = default;return true;}catch (Exception ex){obj = default;errorMsg = ex.Message;return false;}
}

7. 反射问题

参考项目CodeWF.NetWeaver

  1. 创建指定类型的List<T>Dictionary<T>实例:
public static object CreateInstance(Type type)
{var itemTypes = type.GetGenericArguments();if (typeof(IList).IsAssignableFrom(type)){var lstType = typeof(List<>);var genericType = lstType.MakeGenericType(itemTypes.First());return Activator.CreateInstance(genericType)!;}else{var dictType = typeof(Dictionary<,>);var genericType = dictType.MakeGenericType(itemTypes.First(), itemTypes[1]);return Activator.CreateInstance(genericType)!;}
}
  1. 反射调用List<T>Dictionary<T>Add方法添加元素失败,下面是伪代码:
// List<T>
var addMethod = type.GetMethod("Add");
addMethod.Invoke(obj, new[]{ child })// Dictionary<Key, Value>
var addMethod = type.GetMethod("Add");
addMethod.Invoke(obj, new[]{ key, value })

解决办法,转换为实现的接口调用:

// List<T>
(obj as IList).Add(child);// Dictionary<Key, Value>
(obj as IDictionary)[key] = value;
  1. 获取数组、List<T>Dictionary<key, value>的元素个数

同上面Add方法反射获取Length或Count属性皆返回0,value.Property("Length", 0),封装的Property非AOT运行正确:

public static T Property<T>(this object obj, string propertyName, T defaultValue = default)
{if (obj == null) throw new ArgumentNullException(nameof(obj));if (string.IsNullOrEmpty(propertyName)) throw new ArgumentNullException(nameof(propertyName));var propertyInfo = obj.GetType().GetProperty(propertyName);if (propertyInfo == null){return defaultValue;}var value = propertyInfo.GetValue(obj);try{return (T)Convert.ChangeType(value, typeof(T));}catch (InvalidCastException){return defaultValue;}
}

AOT成功:直接通过转换为基类型或实现的接口调用属性即可:

// 数组
var length = ((Array)value).Length;// List<T>if (value is IList list)
{var count = list.Count;
}// Dictionary<key, value>
if (value is IDictionary dictionary)
{var count = dictionary.Count;
}

8. Windows 7支持

如遇AOT后无法在Windows 7运行,请添加YY-Thunks包:

<PackageReference Include="YY-Thunks" Version="1.1.4-Beta3" />

并指定目标框架为net9.0-windows

9. Winform\兼容XP

如果第8条后还运行不了,请参考上一篇文章《.NET 9 AOT的突破 - 支持老旧Win7与XP环境 - 码界工坊 (dotnet9.com)》添加VC-LTL包,这里不赘述。

10. 其他

还有许多其他需要注意的地方,后续想起来逐渐完善本文。

三、总结

AOT 发布测试虽然过程中可能会遇到诸多问题,但通过及时的测试和正确的配置调整,最终能够实现项目的顺利发布。希望以上总结的经验能对大家在 AOT 使用过程中有所帮助,让大家在开发过程中少走弯路,提高项目的开发效率和质量。同时,也期待大家在实践中不断探索和总结,共同推动技术的进步和发展。

AOT可参考项目:

  • CodeWF.NetWeaver: https://github.com/dotnet9/CodeWF.NetWeaver
  • CodeWF.Tools:https://github.com/dotnet9/CodeWF.Tools
  • CodeWF.Toolbox:https://github.com/dotnet9/CodeWF.Toolbox

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/827500.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

教师提前批试讲-注意事项

教师提前批试讲-注意事项

大白菜装系统

在平时工作中,作为程序员,最苦逼的是公司的电脑坏了,都找你。我想说我是程序员,不是修电脑的,但是架不住小姐姐的热情,还是做了。 装系统流程: 第一步:前期准备 1、使用【大白菜】制作U盘启动盘。 2、查询机型的U盘启动快捷键。 3、准备一个ISO/GHO镜像。 第二步:插入…

实验11:装饰模式

本次实验属于模仿型实验,通过本次实验学生将掌握以下内容: 1、理解装饰模式的动机,掌握该模式的结构; 2、能够利用装饰模式解决实际问题。[实验任务一]:手机功能的升级用装饰模式模拟手机功能的升级过程:简单的手机(SimplePhone)在接收来电时,会发出声音提醒主人;而Ja…

Pbootcms网站,从Apache切换为Nginx后网站打不开

打开网站设置登录宝塔面板。 选择需要配置的网站,点击“设置”。进入伪静态设置在网站设置页面中,找到并点击“伪静态”选项卡。添加Nginx伪静态规则在伪静态设置中,清空原有规则或选择自定义规则。 输入以下Nginx伪静态规则:location / {if (!-e $request_filename){rewri…

2024/11/06

软件设计 实验10:组合模式 用透明组合模式实现教材中的“文件夹浏览”这个例子。 类图 public abstract class AbstractFile {public abstract void add(AbstractFile element);public abstract void remove(AbstractFile element);public abstract void display(int depth); …

SQLSTATE[HY000] [1045] Access denied for user ‘root‘@‘localhost‘ (using password: YES)

错误解析错误代码:SQLSTATE[HY000] [1045] 错误信息:Access denied for user ‘root’@‘localhost’ (using password: YES)可能的原因密码错误:提供的密码与数据库中存储的密码不匹配。 用户权限问题:用户root可能没有从localhost访问数据库的权限。 配置文件问题:MySQL…

帝国CMS更改域名后信息地址中的域名不变解决方法

修改系统参数设置进入“系统参数设置 - 基本属性 - 网站地址”,设置为 /。 不要填写具体的域名,以避免信息地址变成绝对地址。更新信息页地址进入“系统 - 数据更新 - 更新信息页地址”,选择相应的数据表,点击“扫码添加技术【解决问题】专注中小企业网站建设、网站安全12年…

帝国CMS系统后台批量删除不带标题图片信息

执行SQL语句删除不带标题图片的信息:delete from [表前缀]_ecms_news where titlepic = ; delete from [表前缀]_ecms_news_index where id not in (select id from [表前缀]_ecms_news); delete from [表前缀]_ecms_news_data_1 where id not in (select id from [表前缀]_ec…

帝国CMS留言模板提示请输入姓名,邮箱与留言内容解决方法

检查表单提交:确认提交地址、POST 数据和表单字段正确。 在表单中添加隐藏字段 bid: <input name="bid" type="hidden" value="分类ID" />扫码添加技术【解决问题】专注中小企业网站建设、网站安全12年。熟悉各种CMS,精通PHP+MYSQL、HT…

信息安全新篇章:车企图纸安全外发创新方案!

车企的图纸在其业务流程中会与多个环节产生交集,并涉及到图纸安全外发传输。以下是主要涉及的环节及图纸传输发送的相关情况: 1.市场分析报告、概念草图、初步布置图等图纸:需要在设计团队内部进行传输,以供讨论和修改。同时,需要发送给供应商或合作伙伴进行初步评估和反馈…

宝塔安装好后网址打不开的可能原因及解决方法

检查域名解析确认域名是否正确解析到服务器的IP地址。 可以使用 ping 命令测试域名解析是否正确。检查服务器网络确认服务器的网络连接是否正常。 尝试从服务器内部访问外部网站,确保网络畅通。检查防火墙设置确认服务器的防火墙设置是否允许HTTP/HTTPS流量通过。 默认情况下,…

腾讯云服务器配置windows安装宝塔

在腾讯云服务器上配置 Windows 并安装宝塔面板的步骤如下: 1. 购买和配置腾讯云 Windows 服务器登录腾讯云控制台:访问 腾讯云官网 并登录你的账号。创建 Windows 服务器:进入“云服务器”页面,点击“创建实例”。 选择 Windows 操作系统,例如 Windows Server 2019 数据中…