Jb
I have most of it working.
Although I am having two issue
1. trouble importing a constructor. I always seem to get a "Invalid
Typeref token"
2. note in my code I had to use reflection to access a private
constructor in Cecil
the method I am trying to import is as follows (simplified for testing purposes)
public void OnPropertyChanged(string propertyName)
{
new PropertyChangedEventArgs(propertyName);
}
And here is my import method. Note where I am trying really hard to
import the missing type. I am not sure what type I am missing
private MethodDefinition CopyMethod(MethodDefinition
templateMethod, TypeDefinition targetType)
{
var targetModule = targetType.Module;
var newMethod = new MethodDefinition(templateMethod.Name,
templateMethod.Attributes,
targetModule.Import(templateMethod.ReturnType));
foreach (var variableDefinition in templateMethod.Body.Variables)
{
newMethod.Body.Variables.Add(new
VariableDefinition(targetModule.Import(variableDefinition.VariableType)));
}
foreach (var parameterDefinition in templateMethod.Parameters)
{
newMethod.Parameters.Add(new
ParameterDefinition(targetModule.Import(parameterDefinition.ParameterType)));
}
foreach (var instruction in templateMethod.Body.Instructions)
{
var constructorInfo =
typeof(Instruction).GetConstructor(BindingFlags.NonPublic |
BindingFlags.Instance, null, new[] { typeof(OpCode), typeof(object) },
null);
var newInstruction =
(Instruction)constructorInfo.Invoke(new[] { instruction.OpCode ,
instruction.Operand});
var fieldDefinition = newInstruction.Operand as FieldDefinition;
if (fieldDefinition != null)
{
targetModule.Import(fieldDefinition.FieldType);
newInstruction.Operand = targetType.Fields.First(x
=> x.Name == fieldDefinition.Name);
}
if (newInstruction.Operand is MethodReference)
{
//Try really hard to import type
var methodReference =
(MethodReference)newInstruction.Operand;
targetModule.Import(methodReference.MethodReturnType.ReturnType);
targetModule.Import(methodReference.DeclaringType);
targetModule.Import(methodReference);
}
if (newInstruction.Operand is TypeReference)
{
targetModule.Import(newInstruction.Operand as
TypeReference);
}
newMethod.Body.Instructions.Add(newInstruction);
}
targetType.Methods.Add(newMethod);
return newMethod;
}
On Tue, Nov 2, 2010 at 8:06 PM, Jb Evain <[email protected]> wrote:
> Hey Simon,
>
> Sadly there's nothing in Cecil or in Cecil.Rocks to help you with that
> right now. Also, the approach you posted won't work. You want to do a
> deep clone of the method, which will take care of properly importing
> all types in the module you're copying.
>
> It means that you want to have:
>
> var target_module = ...;
>
> var new_method = new MethodDefinition (template.Name,
> template.Attribute, target_module.Import (template.ReturnType));
>
> new_methods.Parameters.Add (new ParameterDefinition
> (target_module.Import (template.Parameters [0].ParameterType)));
>
> And so on.
>
> And it may actually be not complete enough. You might want to have a
> special strategy for importing types. Let say you have a method
> Foo::Bar in the module foo.dll. You want to clone it into Baz::Bar
> into baz.dll. If the return type of the template method is a string,
> you want to create a reference to string in baz.dll. But what if
> Foo::Bar returns a type defined in foo.dll, say Bang ? You have to
> decide whether you clone the whole Bang type into baz.dll, or simply
> create a reference to Bang from foo into baz.dll.
>
> So it's not simple, you have to know what you want and what you're doing :)
>
> On Tue, Nov 2, 2010 at 8:14 AM, Simon Cropp <[email protected]> wrote:
>> I am trying to copy a very simple method from one type to another Type
>>
>> So far I have this
>>
>> private MethodDefinition CopyMethod(MethodDefinition
>> templateMethod, TypeDefinition targetType)
>> {
>> var newMethod = new
>> MethodDefinition(templateMethod.Name,
>> templateMethod.Attributes, templateMethod.ReturnType);
>>
>> foreach (var parameterDefinition in templateMethod.Parameters)
>> {
>> newMethod.Parameters.Add(parameterDefinition);
>> }
>> foreach (var instruction in templateMethod.Body.Instructions)
>> {
>> newMethod.Body.Instructions.Add(instruction);
>> }
>> targetType.Methods.Add(newMethod);
>> return newMethod;
>> }
>>
>> But I am getting a "Invalid Typeref token." when I try to execute the code.
>>
>> Any pointers?
>>
>> --
>> --
>> mono-cecil
>
> --
> --
> mono-cecil
--
--
mono-cecil