private static void CreateMethodPrototypesDictionary(MethodDefinition method) { var prototypeType = method.DeclaringType.NestedTypes.Single(m => m.Name == "PrototypeClass"); var delegateType = prototypeType.NestedTypes.Single(m => m.Name == "Callback_" + ComposeFullMethodName(method)); var dicType = method.Module.Import(typeof(Dictionary<Type, object>)); var dicConst = method.Module.Import(typeof(Dictionary<Type, object>).GetConstructor(Type.EmptyTypes)); //Create the dictionary itself var protoDic = new FieldDefinition('_'+ComposeFullMethodName(method), FieldAttributes.Private, dicType); protoDic.DeclaringType = prototypeType; prototypeType.Fields.Add(protoDic); //Create property for the dictionary. var Property = new PropertyDefinition(ComposeFullMethodName(method), PropertyAttributes.None, dicType); var get = new MethodDefinition("get_" + Property.Name, MethodAttributes.Assembly | MethodAttributes.SpecialName | MethodAttributes.CompilerControlled | MethodAttributes.HideBySig, dicType); var set = new MethodDefinition("set_" + Property.Name, MethodAttributes.Assembly | MethodAttributes.SpecialName | MethodAttributes.CompilerControlled | MethodAttributes.HideBySig, method.Module.Import(typeof(void))); //IL getter //used to create the dictionary object if it's not initialized. get.Body.Variables.Add(new VariableDefinition(dicType)); get.Body.Variables.Add(new VariableDefinition(method.Module.Import(typeof(bool)))); get.Body.InitLocals = true; set.Body.InitLocals = true; ICollection<Instruction> jmpReplacements = new Collection<Instruction>(); var il = get.Body.GetILProcessor(); //check for dictionary existance il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, protoDic.Instance()); // class [mscorlib]System.Collections.Generic.Dictionary`2<class [mscorlib]System.Type, object> valuetype Cheese.GenericStorage`1/Test<!T>::Dict il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Ceq); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ceq); il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Ldloc_1); il.Emit(OpCodes.Brtrue_S, label("returnDict")); // IL_001e //create dictionary il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Newobj,dicConst); // instance void class [mscorlib]System.Collections.Generic.Dictionary`2<class [mscorlib]System.Type, object>::.ctor() il.Emit(OpCodes.Stfld, protoDic.Instance()); // class [mscorlib]System.Collections.Generic.Dictionary`2<class [mscorlib]System.Type, object> valuetype Cheese.GenericStorage`1/Test<!T>::Dict il.SetLabel("returnDict"); //return dictionary reference il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, protoDic.Instance()); // class [mscorlib]System.Collections.Generic.Dictionary`2<class [mscorlib]System.Type, object> valuetype Cheese.GenericStorage`1/Test<!T>::Dict il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ret); //IL setter set.Body.GetILProcessor().Emit(OpCodes.Ldarg_0); set.Body.GetILProcessor().Emit(OpCodes.Ldarg_1); set.Body.GetILProcessor().Emit(OpCodes.Stfld, protoDic.Instance()); set.Body.GetILProcessor().Emit(OpCodes.Ret); Property.GetMethod = get; prototypeType.Methods.Add(get); set.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.None, dicType)); Property.SetMethod = set; prototypeType.Methods.Add(set); prototypeType.Properties.Add(Property); //Create set* method var setMethod = new MethodDefinition("Set" + ComposeFullMethodName(method), MethodAttributes.Public | MethodAttributes.HideBySig, method.Module.Import(typeof (void))); setMethod.ImportGenericParams(method); var dt = new GenericInstanceType(delegateType); foreach (var param in method.DeclaringType.GenericParameters.Concat(setMethod.GenericParameters)) dt.GenericArguments.Add(param); setMethod.Parameters.Add(new ParameterDefinition("code", ParameterAttributes.None, dt)); var systemTypeClass = method.Module.Import(typeof(Type)); var TypeFromHandle = method.Module.Import(systemTypeClass.Resolve().Methods.Single(m => m.Name == "GetTypeFromHandle")); var dictProperty = prototypeType.Properties.Single(m => m.Name == ComposeFullMethodName(method)); Type[] systemFuncs = { typeof(Func<>), typeof(Func<,>), typeof(Func<,,>), typeof(Func<,,,>), typeof(Func<,,,,>)}; var systemFuncClass = method.Module.Import(systemFuncs[method.GenericParameters.Count-1]); systemFuncClass = new GenericInstanceType(systemFuncClass); foreach (var param in method.GenericParameters) ((GenericInstanceType)systemFuncClass).GenericArguments.Add(param); var dictType = method.Module.Import(typeof(Dictionary<Type, object>)); var dictAddMethod = method.Module.Import(dictType.Resolve().Methods.Single(m => m.Name == "Add")); dictAddMethod.DeclaringType = dictType; il = setMethod.Body.GetILProcessor(); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, dictProperty.GetMethod.Instance()); // instance class [mscorlib]System.Collections.Generic.Dictionary`2<class [mscorlib]System.Type, object> valuetype Cheese.GenericStorage`1/Test<!T>::get_DictAccesor() il.Emit(OpCodes.Ldtoken, systemFuncClass); // class [System.Core]System.Func`2<!!L, !!H> il.Emit(OpCodes.Call, TypeFromHandle); // class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Callvirt,dictAddMethod); // instance void class [mscorlib]System.Collections.Generic.Dictionary`2<class [mscorlib]System.Type, object>::Add(!0, !1) il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ret); prototypeType.Methods.Add(setMethod); setMethod.DeclaringType = prototypeType; }