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.
精彩评论