How to generate delegate type from MethodReference

55 views
Skip to first unread message

blez

unread,
Sep 13, 2012, 8:36:45 AM9/13/12
to mono-...@googlegroups.com
Hello. I tried this and I'm doing something wrong. The output is always invalid (in PEVerify).

TypeDefinition CreateDelegates(TypeDefinition type, MethodReference source) {
           
var desiredname = source.Name.ToLowerInvariant() + "__DELEGATE";
           
var module = type.Module;

           
if (type.HasNestedTypes) {
               
foreach (var deleg in type.NestedTypes) {
                   
if (deleg.Name == desiredname) return deleg;
               
}
           
}

           
var multiDelegateType = module.Import(typeof(MulticastDelegate));
           
var voidType = module.Import(typeof(void));
           
var objectType = module.Import(typeof(object));
           
var nativeIntType = module.Import(typeof(IntPtr));
           
var asyncCallbackType = module.Import(typeof(AsyncCallback));
           
var asyncResultType = module.Import(typeof(IAsyncResult));

           
// Create new delegate type
           
var dlgtype = new TypeDefinition("", desiredname, TypeAttributes.Sealed | TypeAttributes.NestedAssembly, multiDelegateType);
            type
.NestedTypes.Add(dlgtype);

           
var constructor = new MethodDefinition(".ctor", MethodAttributes.Public | MethodAttributes.CompilerControlled | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig, voidType);

            constructor
.IsRuntime = true;
            constructor
.HasThis = true;
            constructor
.IsHideBySig = true;
           
//constructor.IsVirtual = true;
            constructor
.IsPublic = true;

            constructor
.Parameters.Add(new ParameterDefinition("'object'", ParameterAttributes.None, objectType));
            constructor
.Parameters.Add(new ParameterDefinition("'method'", ParameterAttributes.None, nativeIntType));
            dlgtype
.Methods.Add(constructor);

           
var begininvoke = new MethodDefinition("BeginInvoke", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, asyncResultType);
            begininvoke
.IsRuntime = true;
            begininvoke
.HasThis = true;
            begininvoke
.IsHideBySig = true;
            begininvoke
.IsRuntimeSpecialName = true;
            begininvoke
.IsSpecialName = true;
            begininvoke
.IsPublic = true;
            begininvoke
.IsVirtual = true;

           
foreach (var para in source.Parameters) {
                begininvoke
.Parameters.Add(new ParameterDefinition(para.Name, para.Attributes, para.ParameterType));
           
}

            begininvoke
.Parameters.Add(new ParameterDefinition("callback", ParameterAttributes.None, asyncCallbackType));
            begininvoke
.Parameters.Add(new ParameterDefinition("object", ParameterAttributes.None, objectType));

            dlgtype
.Methods.Add(begininvoke);

           
var endinvoke = new MethodDefinition("EndInvoke", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, voidType);
            endinvoke
.Parameters.Add(new ParameterDefinition("result", ParameterAttributes.None, asyncResultType));

            endinvoke
.IsRuntime = true;
            endinvoke
.HasThis = true;
            endinvoke
.IsHideBySig = true;
            endinvoke
.IsRuntimeSpecialName = true;
            endinvoke
.IsSpecialName = true;
            endinvoke
.IsPublic = true;

            dlgtype
.Methods.Add(endinvoke);

           
var invoke = new MethodDefinition("Invoke", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, voidType);

           
foreach (var para in source.Parameters) {
                invoke
.Parameters.Add(new ParameterDefinition(para.Name, para.Attributes, para.ParameterType));
           
}

            invoke
.IsRuntime = true;
            invoke
.HasThis = true;
            invoke
.IsHideBySig = true;
            invoke
.IsVirtual = true;
            invoke
.IsPublic = true;

            dlgtype
.Methods.Add(invoke);

           
return dlgtype;

       
}


What I'm doing wrong? PEVerify says the types cannot be loaded.

Jb Evain

unread,
Sep 13, 2012, 9:49:57 AM9/13/12
to mono-...@googlegroups.com
Hey,

That looks quite OKish:

* Remove the IsCompiledControlled from the ctor.
* Make sure the version of runtime of assembly you're modifying is the same as the runtime you're using the patch the assembly, otherwise using the System.Reflection type system is going to create some references to another runtime.
* Also in some places you repeat the flags, there's no need to say IsPublic = true if you passed it in the ctor, but that should not be an issue.

Jb
> --
> --
> mono-cecil

Reply all
Reply to author
Forward
0 new messages