开发者

Using Mono.Cecil to add an Indexer to a TypeDefinition

I'm using JB Evain's Mono.Cecil to perform some byte-code manipulation on compiled DLL's. Part of this project is to inject properties into TypeDefinitions, effectively turning compiled getters/setters into the C# Properties pattern using PropertyDefinitions. This part is working well.

However, I would like to add an indexer to the TypeDefinition but I cannot find any documentation or advice on how best to achieve this. The methods which will be used to process the index requests are already in place:

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

All i need to do is add the metadata to convert these into indexers....

Any ideas 开发者_StackOverflow中文版/ thoughts would be greatly apprecaited!


Indexers, metadata wise, are simple properties. Only the type is decorated with a special attribute to tell that the property is an indexer. Here's a sample implementation which adds a new Item property that is recognized as an indexer, and delegates to the existing methods.

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);

Of course you could also just create a property which points to the existing methods, as long as you have the proper attribute.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜