private static TypeDefinition CreatePrototypeType(TypeDefinition type) { TypeDefinition result = new TypeDefinition(null, "PrototypeClass", TypeAttributes.Sealed | TypeAttributes.NestedPublic | TypeAttributes.BeforeFieldInit | TypeAttributes.SequentialLayout, type.Module.Import(typeof(ValueType))); result.ImportGenericParams(type); type.NestedTypes.Add(result); result.DeclaringType = type; return result; }
private static TypeDefinition CreateDeligateType(MethodDefinition method) { string deligateName = "Callback_" + ComposeFullMethodName(method); var parentType = method.DeclaringType.NestedTypes.Single(m => m.Name == "PrototypeClass"); TypeReference multicastDeligateType = parentType.Module.Import(typeof(MulticastDelegate)); TypeReference voidType = parentType.Module.Import(typeof(void)); TypeReference objectType = parentType.Module.Import(typeof(object)); TypeReference intPtrType = parentType.Module.Import(typeof(IntPtr)); TypeDefinition result = new TypeDefinition(null, deligateName, TypeAttributes.Sealed | TypeAttributes.NestedPublic | TypeAttributes.RTSpecialName, multicastDeligateType); result.ImportGenericParams(parentType); if (method.HasGenericParameters) result.ImportGenericParams(method); //create constructor var constructor = new MethodDefinition(".ctor", MethodAttributes.Public | MethodAttributes.CompilerControlled | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig, voidType); constructor.Parameters.Add(new ParameterDefinition("object", ParameterAttributes.None, objectType)); constructor.Parameters.Add(new ParameterDefinition("method", ParameterAttributes.None, intPtrType)); constructor.IsRuntime = true; result.Methods.Add(constructor); //not a good solution, but it don't work any other way var ret = method.ReturnType; if (method.ReturnType.IsGenericParameter && method.GenericParameters.SingleOrDefault(m=>m.Name==method.ReturnType.Name)!=null) ret = result.GenericParameters.SingleOrDefault(m => m.Name == method.ReturnType.Name); //create Invoke var invoke = new MethodDefinition("Invoke", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, ret); invoke.IsRuntime = true; if (!method.IsStatic) { invoke.Parameters.Add(new ParameterDefinition("self", ParameterAttributes.None, method.DeclaringType.Instance())); } foreach (var param in method.Parameters) { //thanks to cecil - it can't resolve param type properly. //TODO: prettify/eliminate that hack var type = result.GenericParameters.FirstOrDefault(m => m.Name == param.ParameterType.Name.Replace("&","")); if(type==null) invoke.Parameters.Add(new ParameterDefinition(param.Name, param.Attributes, param.ParameterType)); else invoke.Parameters.Add(new ParameterDefinition(param.Name, param.Attributes, type)); } result.Methods.Add(invoke); //the rest of the process result.DeclaringType = parentType; parentType.NestedTypes.Add(result); return result; }