我正在使用JB Evain的Mono.Cecil对已编译的DLL执行一些字节码操作。该项目的一部分是将属性注入TypeDefinitions,使用PropertyDefinitions有效地将编译的getter / setter转换为C#Properties模式。这部分运作良好。
但是,我想在TypeDefinition中添加一个索引器,但是我找不到任何关于如何最好地实现此目的的文档或建议。将用于处理索引请求的方法已经到位:
Object getObjectViaIndexer(String str);
void setObjectViaIndexer(String str, object obj);
我需要做的就是添加元数据以将它们转换为索引器....
任何想法/想法都会有很大的意义!
答案 0 :(得分:5)
元数据明智的索引器是简单的属性。只有该类型使用特殊属性进行修饰,以告知该属性是索引器。这是一个示例实现,它添加了一个被识别为索引器的新Item属性,并委托给现有方法。
TypeDefinition type = ...;
// public object get_Item (string str) { ... }
var get_item = new MethodDefinition ("get_Item", MethodAttributes.Public, module.TypeSystem.Object);
set_item.Parameters.Add (new ParameterDefinition ("str", ParameterAttributes.None, module.TypeSystem.String));
type.Methods.Add (get_item);
var il = get_item.Body.GetILProcessor ();
il.Emit (...); // emit call to getObjectViaIndexer
// public void set_Item (string str, object obj) { ... }
var set_item = new MethodDefinition ("set_Item", MethodAttributes.Public, module.TypeSystem.Void);
set_item.Parameters.Add (new ParameterDefinition ("str", ParameterAttributes.None, module.TypeSystem.String));
set_item.Parameters.Add (new ParameterDefinition ("obj", ParameterAttributes.None, module.TypeSystem.Object));
type.Methods.Add (set_item);
il = set_item.Body.GetILProcessor ();
il.Emit (...); // emit call to setObjectViaIndexer
// public object this [string str] { ... }
var item = new PropertyDefinition ("Item", PropertyAttributes.None, module.TypeSystem.Object) {
HasThis = true,
GetMethod = get_item,
SetMethod = set_item,
};
type.Properties.Add (item);
// [DefaultMemberAttribute("Item")]
var default_member = new CustomAttribute (module.Import (typeof (System.Reflection.DefaultMemberAttribute).GetConstructor (new [] { typeof (string) })));
default_member.ConstructorArguments.Add (new CustomAttributeArgument(module.TypeSystem.String, "Item"));
type.CustomAttributes.Add (default_member);
当然,您也可以创建一个指向现有方法的属性,只要您具有适当的属性即可。