2

我正在使用 JB Evain 的 Mono.Cecil 对已编译的 DLL 执行一些字节码操作。该项目的一部分是将属性注入 TypeDefinitions,使用 PropertyDefinitions 有效地将编译的 getter/setter 转换为 C# Properties 模式。这部分运作良好。

但是,我想向 TypeDefinition 添加一个索引器,但我找不到任何关于如何最好地实现这一点的文档或建议。将用于处理索引请求的方法已经到位:

Object getObjectViaIndexer(String str);
void setObjectViaIndexer(String str, object obj);

我需要做的就是添加元数据以将它们转换为索引器......

任何想法/想法将不胜感激!

4

1 回答 1

6

索引器,元数据明智的,是简单的属性。只有类型用特殊属性修饰,以告知该属性是一个索引器。这是一个示例实现,它添加了一个被识别为索引器的新 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);

当然,您也可以只创建一个指向现有方法的属性,只要您具有适当的属性即可。

于 2011-08-25T20:44:54.077 回答