public void EmitExecuteMethodBody(EmitGenerator gen, LocalBuilder instance) { // Use MakeByRefType(), because this is an out (ref) parameter in the method signature. var paramType = _dependencyProvider.TargetType.MakeByRefType(); var paramTypes = new Type[] { typeof(InjectionContext), paramType }; var createObjectMethod = _paramField.FieldType.GetMethod("CreateObject", paramTypes); if (createObjectMethod == null) { throw new ImpossibleException(); } _paramValue = gen.DeclareLocal(_dependencyProvider.TargetType); gen.LoadThis(); gen.LoadField(_paramField); gen.LoadArgument(1); gen.LoadLocalAddress(_paramValue); gen.CallMethod(createObjectMethod); }
public void EmitExecuteMethodBody(EmitGenerator gen, LocalBuilder instance) { if (_dependencyProviders == null || _dependencyProviders.Length == 0) { //var dummyClass = new DummyClass(); gen.New(_injectedCtor); gen.StoreLocal(instance); } else { //IObjectRegistration p1; //IConfigurationModule p2; //ILifetimeScope p3; //_parameterMerger.Merge(context, out p1, out p2, out p3); //instance = new DummyClass(p1, p2, p3); var mergeMethod = _paramMergerField.FieldType.GetMethod("Merge"); if (mergeMethod == null) { throw new ImpossibleException(); } #region Define Locals //IObjectRegistration p1; //IConfigurationModule p2; //ILifetimeScope p3; var ctorParamBuilders = new LocalBuilder[_dependencyProviders.Length]; for (int i = 0; i < _dependencyProviders.Length; i++) { ctorParamBuilders[i] = gen.DeclareLocal(_dependencyProviders[i].TargetType); } #endregion #region _parameterMerger.Merge(context, out p1, out p2, out p3); gen.LoadThis(); gen.LoadField(_paramMergerField); gen.LoadArgument(1); for (int i = 0; i < ctorParamBuilders.Length; i++) { gen.LoadLocalAddress(ctorParamBuilders[i]); } gen.CallMethod(mergeMethod); #endregion #region instance = new DummyClass(p1, p2, p3); for (int i = 0; i < ctorParamBuilders.Length; i++) { gen.LoadLocal(ctorParamBuilders[i]); } gen.New(_injectedCtor); gen.StoreLocal(instance); #endregion } }
static void EmitMergeMethodBody(EmitGenerator gen, GenericTypeParameterBuilder[] genParamBuilders, FieldBuilder[] depProviderFields) { // var myParams = context.Parameters; var myParams = gen.DeclareLocal(ParameterSetType); gen.LoadArgument(1); gen.CallMethod(GetInjectionContextParameters); gen.StoreLocal(myParams); #region If (myParams == null || myParams.Length == 0) condition // if (myParams == null || myParams.Length == 0) Goto myParamsIsNullLabel Else Goto myParamsIsNotNullAndLengthNotEqualTo0Label var myParamsIsNullLabel = gen.DefineLabel(); var myParamsIsNotNullAndLengthNotEqualTo0Label = gen.DefineLabel(); gen.LoadLocal(myParams); gen.IfFalseGoto(myParamsIsNullLabel); gen.LoadLocal(myParams); gen.CallMethod(GetParameterLength); gen.IfTrueGoto(myParamsIsNotNullAndLengthNotEqualTo0Label); #endregion var createObjectMethods = new MethodInfo[depProviderFields.Length]; #region if (myParams == null || myParams.Length == 0) block gen.MarkLabel(myParamsIsNullLabel); for (int i = 0; i < depProviderFields.Length; i++) { // _dependency0.CreateObject(context, out param0); // _dependency1.CreateObject(context, out param1); // ... var depProviderField = depProviderFields[i]; gen.LoadThis(); gen.LoadField(depProviderField); gen.LoadArgument(1); // load parameter [context] gen.LoadArgument(i + 2); // load parameter [param0], [param1], [param2]... var createObjectMethod = GetCreateObjectOfDependencyProviderMethod(depProviderField.FieldType); createObjectMethods[i] = createObjectMethod; gen.CallMethod(createObjectMethod); } gen.Return(); #endregion #region if (myParams != null && myParams.Length != 0) block gen.MarkLabel(myParamsIsNotNullAndLengthNotEqualTo0Label); // var paramKind = myParams.ParameterKind; var paramKind = gen.DeclareLocal(typeof(ParameterKind)); gen.LoadLocal(myParams); gen.CallMethod(GetParameterKind); gen.StoreLocal(paramKind); // (Ok)===================================================== var paramKindDefaultCase = gen.DefineLabel(); var paramKindTable = new Label[] { gen.DefineLabel(), gen.DefineLabel() }; gen.LoadLocal(paramKind); gen.Switch(paramKindTable); // switch (paramKind) // case default Goto paramKindDefaultCase gen.Goto(paramKindDefaultCase); // (Ok)===================================================== #region case paramKind = ParameterKind.Positional (Ok) gen.MarkLabel(paramKindTable[0]); // var myParamLength = myParams.Length; var myParamLength = gen.DeclareLocal(typeof(int)); gen.LoadLocal(myParams); gen.CallMethod(GetParameterLength); gen.StoreLocal(myParamLength); // switch (myParamLength) gen.LoadLocal(myParamLength); gen.LoadInt32(1); gen.Substrate(); // myParamLength - 1, this is because the switch branch is starting from 1, instead of 0 var paramLengthDefaultCase = gen.DefineLabel(); var paramLengthTable = new Label[depProviderFields.Length]; for (int i = 0; i < depProviderFields.Length; i++) { paramLengthTable[i] = gen.DefineLabel(); } gen.Switch(paramLengthTable); // case default Goto paramLengthDefaultCase gen.Goto(paramLengthDefaultCase); #region case i for myParamLength for (int i = 0; i < depProviderFields.Length; i++) { gen.MarkLabel(paramLengthTable[i]); for (int j = 0; j < depProviderFields.Length; j++) { if (j <= i) { // something like: param0 = GetPositionalDependencyObject(_depProvider0, myParams[0], context); // load _depProvider0 gen.LoadThis(); gen.LoadField(depProviderFields[j]); // load myParams[0] gen.LoadLocal(myParams); gen.LoadInt32(j); gen.CallMethod(GetItem); // load context gen.LoadArgument(1); var genParamType = genParamBuilders[j]; gen.CallMethod(OpenGetPositionalDependencyObjectMethod.MakeGenericMethod(genParamType)); //gen.StoreObject(genParamType); gen.StoreArgument(j + 2); } else { // something like: _depProvider1.CreateObject(context, out param1); // load _depProvider1 gen.LoadThis(); gen.LoadField(depProviderFields[j]); // load context gen.LoadArgument(1); // load param1, its index is j + 2 gen.LoadArgument(j + 2); gen.CallMethod(createObjectMethods[j]); } } gen.Return(); } #endregion #region default case for myParamLength gen.MarkLabel(paramLengthDefaultCase); gen.LoadArgument(1); gen.LoadInt32(depProviderFields.Length); gen.LoadLocal(myParams); gen.CallMethod(GetParameterLength); gen.CallMethod(ParameterNumberExceedsMethod); gen.Throw(); #endregion gen.Return(); #endregion #region case paramKind = ParameterKind.Named (Ok) gen.MarkLabel(paramKindTable[1]); for (int i = 0; i < depProviderFields.Length; i++) { // something like: param0 = GetNamedDependencyObject(_depProvider0, myParams, context); // load _depProvider0 gen.LoadThis(); //gen.LoadThis(); // why do we need this? gen.LoadField(depProviderFields[i]); // load myParams gen.LoadLocal(myParams); // load context gen.LoadArgument(1); var genParamType = genParamBuilders[i]; gen.CallMethod(OpenGetNamedDependencyObjectMethod.MakeGenericMethod(genParamType)); // store to param0, its parameter index is [i + 2] gen.StoreArgument(i + 2); } gen.Return(); #endregion #region default case for ParameterKind (Ok) gen.MarkLabel(paramKindDefaultCase); gen.Throw(ImpossibleExceptionConstructor); #endregion gen.Return(); #endregion }