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

Reply via email to