static private FieldDefinition Intermediate(this MethodDefinition method, MethodDefinition authentic, int neptuneMethodIndex) { var _intermediate = method.DeclaringType.Authority("<Intermediate>").Type(method.IsConstructor ? $"<<Constructor>>" : $"<{method.Name}>", TypeAttributes.NestedPublic | TypeAttributes.Class | TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit); foreach (var _parameter in method.GenericParameters) { _intermediate.GenericParameters.Add(new GenericParameter(_parameter.Name, _intermediate)); } var _field = _intermediate.Field <IntPtr>(Program.Pointer, FieldAttributes.Static | FieldAttributes.Public); FieldReference _fieldReference = _field; MethodReference _authenticReference = authentic; GenericInstanceType _authenticGenericType = null; if (_intermediate.HasGenericParameters) { _intermediate.Field("<NeptuneMethodIndex>", FieldAttributes.Public, neptuneMethodIndex); var _intermediateGenericType = _intermediate.MakeGenericType(_intermediate.GenericParameters); _fieldReference = _intermediateGenericType.Reference(_fieldReference); if (method.DeclaringType.HasGenericParameters) { var _typeParameters = _intermediate.GenericParameters.Take(method.DeclaringType.GenericParameters.Count).ToArray(); var _methodParameters = _intermediate.GenericParameters.Skip(method.DeclaringType.GenericParameters.Count).ToArray(); _authenticGenericType = authentic.DeclaringType.MakeGenericType(_typeParameters); _authenticReference = _authenticGenericType.Reference(authentic, _intermediate.GenericParameters); } else if (method.HasGenericParameters) { _authenticReference = authentic.MakeGenericMethod(_intermediate.GenericParameters); } } var _initializer = _intermediate.Initializer(); var _variable = _initializer.Body.Variable <RuntimeMethodHandle>(); _initializer.Body.Variable <Func <IntPtr> >(); // todo Jens fix generic method in generic type to us ldtoken if (method.DeclaringType.HasGenericParameters && method.HasGenericParameters) { // work around for ldtoken _authenticReference not working correctly for generic method in generic type var methodInstantiatingMethodReference = _initializer.Module.Import(typeof(CNeptuneBase.InstantiationListener).GetMethod(nameof(CNeptuneBase.InstantiationListener.MethodInstantiating))); var _intermediateReference = _intermediate.MakeGenericType(_intermediate.GenericParameters); _initializer.Body.Emit(OpCodes.Ldtoken, _intermediateReference); _initializer.Body.Emit(OpCodes.Ldtoken, _authenticGenericType); _initializer.Body.Emit(OpCodes.Call, _initializer.DeclaringType.Module.Import(Program.GetTypeFromHandle)); _initializer.Body.Emit(OpCodes.Call, _initializer.DeclaringType.Module.Import(methodInstantiatingMethodReference)); } else { _initializer.Body.Emit(_authenticReference); } _initializer.Body.Emit(OpCodes.Callvirt, Program.GetMethodHandle); _initializer.Body.Emit(OpCodes.Stloc_0); _initializer.Body.Emit(OpCodes.Ldloca_S, _variable); _initializer.Body.Emit(OpCodes.Callvirt, Program.GetFunctionPointer); _initializer.Body.Emit(OpCodes.Stsfld, _fieldReference); if (_intermediate.HasGenericParameters) { var methodInstantiatedMethodReference = _initializer.Module.Import(typeof(CNeptuneBase.InstantiationListener).GetMethod(nameof(CNeptuneBase.InstantiationListener.MethodInstantiated))); var _intermediateReference = _intermediate.MakeGenericType(_intermediate.GenericParameters); _initializer.Body.Emit(OpCodes.Ldtoken, _intermediateReference); _initializer.Body.Emit(OpCodes.Call, _initializer.DeclaringType.Module.Import(Program.GetTypeFromHandle)); _initializer.Body.Emit(OpCodes.Call, _initializer.DeclaringType.Module.Import(methodInstantiatedMethodReference)); } //TODO : IOC of AOP !? What the? in fact it will be used to be able to inject on method on demand but a late as possible. //Action<MethodBase> _update; //lock (AppDomain.CurrentDomain.Evidence.SyncRoot) { _update = AppDomain.CurrentDomain.GetData("<Neptune<Update>>") as Action<MethodBase>; } //if (_update != null) { _update(...); } _initializer.Body.Emit(OpCodes.Ret); _initializer.Body.OptimizeMacros(); return(_field); }