简体   繁体   中英

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 / 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM