使用Mono.Cecil给消息类自动添加Attribute
C#的序列化库很多通过注解Attribute来实现,比如Protobuf-net,Messagepack等。如果手动添加注解,会比较麻烦,尤其在切换序列化库的时候,需要更改对应的注解。
这里实现了一个使用Mono.Cecil来自动添加注解的类,当程序编译后,会修改对应的dll来实现效果。
遇到的坑:IDE对于IL级别的错误没有充分清晰的错误提示,需要自己折腾一会儿,去花时间排查问题。【比如注解应该加在Property上的,加在了Field上 /doge】
public class CecilUser
{
public static void Work(string fileName)
{
using (var module = ModuleDefinition.ReadModule(fileName, new ReaderParameters { ReadWrite = true }))
{
// Modify the assembly
foreach (TypeDefinition type in module.Types)
{
if (!type.IsPublic)
continue;
if (!type.IsClass)
continue;
if (ContainsAttribute(type.CustomAttributes, nameof(MessagePackObjectAttribute)))
continue;
ModifyType(module, type);
}
module.Write(); // Write to the same file that was used to open the file
}
}
public static bool ContainsAttribute(Collection<CustomAttribute> attrCollection, string attributeName)
{
foreach (var typeAttr in attrCollection)
{
if (typeAttr.AttributeType.FullName.Contains(attributeName))
return true;
}
return false;
}
private static void ModifyType(ModuleDefinition module, TypeDefinition type)
{
MethodReference classAttrCtor = module.ImportReference(typeof(MessagePackObjectAttribute).GetConstructor(new Type[] { typeof(bool) }));
var typeAttr = new CustomAttribute(classAttrCtor);
var boolTypeRef = module.ImportReference(typeof(bool));
var attrParamType = new CustomAttributeArgument(boolTypeRef, false);
typeAttr.ConstructorArguments.Add(attrParamType);
type.CustomAttributes.Add(typeAttr);
int keyIndex = 0;
foreach(var property in type.Properties)
{
if (ContainsAttribute(property.CustomAttributes, nameof(KeyAttribute)))
continue;
MethodReference fieldAttrCtor = module.ImportReference(typeof(KeyAttribute).GetConstructor(new Type[] { typeof(int) }));
var attr = new CustomAttribute(fieldAttrCtor);
var intTypeRef = module.ImportReference(typeof(int));
var attrParam = new CustomAttributeArgument(intTypeRef, keyIndex++);
attr.ConstructorArguments.Add(attrParam);
property.CustomAttributes.Add(attr);
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!