/// <summary> /// Wraps the method. /// </summary> public void Wrap(WrapContext context) { if (this.m_Method.CustomAttributes.Any(c => c.AttributeType.Name == "LocalAttribute")) return; this.m_TraceSource.TraceEvent(TraceEventType.Information, 0, "Modifying {0} for distributed processing", this.m_Method.Name); // Generate the direct invocation class. TypeDefinition idc = this.GenerateDirectInvokeClass(); // Get a list of existing instructions. Collection<Instruction> instructions = this.m_Method.Body.Instructions; // Get a reference to the context setting method. var assignNodeContext = new MethodReference("AssignNodeContext", this.m_Type.Module.Import(typeof(void)), this.m_Type.Module.Import(typeof(DpmConstructContext))); assignNodeContext.Parameters.Add(new ParameterDefinition(this.m_Type.Module.Import(typeof(object)))); // Create a new Action delegate using those instructions. TypeReference mdr = this.m_Method.ReturnType; MethodDefinition md = new MethodDefinition(this.m_Method.Name + "__Distributed0", MethodAttributes.Private, mdr); md.Body = new MethodBody(md); md.Body.InitLocals = true; md.Body.Instructions.Clear(); foreach (Instruction ii in instructions) { if (ii.OpCode == OpCodes.Newobj) { md.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0)); md.Body.Instructions.Add(Instruction.Create(OpCodes.Call, assignNodeContext)); } md.Body.Instructions.Add(ii); } foreach (VariableDefinition l in this.m_Method.Body.Variables) { md.Body.Variables.Add(l); } foreach (ExceptionHandler ex in this.m_Method.Body.ExceptionHandlers) { md.Body.ExceptionHandlers.Add(ex); } foreach (ParameterDefinition p in this.m_Method.Parameters) { md.Parameters.Add(p); } foreach (GenericParameter gp in this.m_Method.GenericParameters) { GenericParameter gpn = new GenericParameter(gp.Name, md); gpn.Attributes = gp.Attributes; foreach (TypeReference tr in gp.Constraints) { gpn.Constraints.Add(tr); } md.GenericParameters.Add(gpn); } this.m_Type.Methods.Add(md); Utility.AddAttribute(md, typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute), this.m_Module); // Get the ILProcessor and create variables to store the delegate variable // and delegate constructor. ILProcessor il = this.m_Method.Body.GetILProcessor(); VariableDefinition vd; MethodReference ct; // Clear the existing instructions and local variables. this.m_Method.Body.ExceptionHandlers.Clear(); this.m_Method.Body.Instructions.Clear(); this.m_Method.Body.Variables.Clear(); // Generate the IL for the delegate definition and fill the vd and ct // variables. TypeDefinition dg = Utility.EmitDelegate(il, idc, md, this.m_Type, out vd, out ct); // Implement the Invoke method in the DirectInvoke class. this.ImplementDirectInvokeClass(idc, dg, md.Parameters, md.ReturnType); // Create the Process4.Providers.DpmEntrypoint::GetProperty method reference. MethodReference getproperty = new MethodReference("GetProperty", this.m_Type.Module.Import(typeof(object)), this.m_Type.Module.Import(typeof(DpmEntrypoint))); getproperty.Parameters.Add(new ParameterDefinition(this.m_Type.Module.Import(typeof(Delegate)))); getproperty.Parameters.Add(new ParameterDefinition(this.m_Type.Module.Import(typeof(object[])))); // Create the Process4.Providers.DpmEntrypoint::SetProperty method reference. MethodReference setproperty = new MethodReference("SetProperty", this.m_Type.Module.Import(typeof(object)), this.m_Type.Module.Import(typeof(DpmEntrypoint))); setproperty.Parameters.Add(new ParameterDefinition(this.m_Type.Module.Import(typeof(Delegate)))); setproperty.Parameters.Add(new ParameterDefinition(this.m_Type.Module.Import(typeof(object[])))); // Create the Process4.Providers.DpmEntrypoint::Invoke method reference. MethodReference invoke = new MethodReference("Invoke", this.m_Type.Module.Import(typeof(object)), this.m_Type.Module.Import(typeof(DpmEntrypoint))); invoke.Parameters.Add(new ParameterDefinition(this.m_Type.Module.Import(typeof(Delegate)))); invoke.Parameters.Add(new ParameterDefinition(this.m_Type.Module.Import(typeof(object[])))); // Generate the local variables like: // * 0 - MultitypeDelegate // * 1 - object[] // * 2 - {return type} (if not void) VariableDefinition v_0 = vd; VariableDefinition v_1 = new VariableDefinition(this.m_Type.Module.Import(typeof(object[]))); VariableDefinition v_2 = new VariableDefinition(md.ReturnType); // Add the variables to the local variable list (delegate is already added). this.m_Method.Body.Variables.Add(v_1); if (v_2.VariableType.Name.ToLower() != "void") { this.m_Method.Body.Variables.Add(v_2); } // Force local variables to be initalized. this.m_Method.Body.InitLocals = true; this.m_Method.Body.MaxStackSize = 10; // Create statement processor for method. StatementProcessor processor = new StatementProcessor(il); // Make a generic version of the delegate method. TypeDefinition btd = this.m_Type; MethodDefinition bmd = md; MethodReference bmr = btd.Module.Import(bmd); GenericInstanceType bti = null; if (this.m_Type.HasGenericParameters) { bti = (GenericInstanceType)Utility.MakeGenericType(this.m_Type, this.m_Type.GenericParameters.ToArray()); bmr = Utility.MakeGeneric(bmr, bti.GenericArguments.ToArray()); } if (this.m_Method.HasGenericParameters) { GenericInstanceMethod gim = new GenericInstanceMethod(bmr); foreach (GenericParameter gp in bmr.GenericParameters) { gim.GenericArguments.Add(gp); } bmr = gim; } foreach (var gp in this.m_Type.GenericParameters) { ((GenericInstanceType)ct.DeclaringType).GenericArguments.Add(gp); } foreach (var gp in this.m_Method.GenericParameters) { ((GenericInstanceType)ct.DeclaringType).GenericArguments.Add(gp); } // Initialize the delegate. processor.Add(new InitDelegateStatement(ct, bmr, v_0)); // Initialize the array. if (this.m_Method.IsSetter) { il.Append(Instruction.Create(OpCodes.Ldloc_0)); } processor.Add( new InitArrayStatement( this.m_Module.Import(typeof(object)), (sbyte)md.Parameters.Count, v_1, new Action<ILProcessor, int>((p, i) => { // Get a reference to the parameter being passed to the method. ParameterDefinition pd = this.m_Method.Parameters[i]; if (i > this.m_Method.Parameters.Count - 1) { return; } // Create IL to copy the value from the parameter directly // into the array, boxing the value if needed. p.Append(Instruction.Create(OpCodes.Ldloc, v_1)); p.Append(Instruction.Create(OpCodes.Ldc_I4_S, (sbyte)i)); p.Append(Instruction.Create(OpCodes.Ldarg_S, pd)); if (pd.ParameterType.IsValueType || pd.ParameterType.IsGenericParameter) { p.Append(Instruction.Create(OpCodes.Box, pd.ParameterType)); } p.Append(Instruction.Create(OpCodes.Stelem_Ref)); }))); // Call the delegate. if (this.m_Method.IsSetter) { processor.Add(new CallStatement(setproperty, new VariableDefinition[] { v_1 }, this.m_Method.ReturnType, v_2)); } else if (this.m_Method.IsGetter) { processor.Add(new CallStatement(getproperty, new VariableDefinition[] { v_0, v_1 }, this.m_Method.ReturnType, v_2)); } else { processor.Add(new CallStatement(invoke, new VariableDefinition[] { v_0, v_1 }, this.m_Method.ReturnType, v_2)); } }
/// <summary> /// Wraps the method. /// </summary> public void Wrap(WrapContext context) { if (this.m_Method.CustomAttributes.Any(c => c.AttributeType.Name == "LocalAttribute")) { return; } this.m_TraceSource.TraceEvent(TraceEventType.Information, 0, "Modifying {0} for distributed processing", this.m_Method.Name); // Generate the direct invocation class. TypeDefinition idc = this.GenerateDirectInvokeClass(); // Get a list of existing instructions. Collection <Instruction> instructions = this.m_Method.Body.Instructions; // Get a reference to the context setting method. var assignNodeContext = new MethodReference("AssignNodeContext", this.m_Type.Module.Import(typeof(void)), this.m_Type.Module.Import(typeof(DpmConstructContext))); assignNodeContext.Parameters.Add(new ParameterDefinition(this.m_Type.Module.Import(typeof(object)))); // Create a new Action delegate using those instructions. TypeReference mdr = this.m_Method.ReturnType; MethodDefinition md = new MethodDefinition(this.m_Method.Name + "__Distributed0", MethodAttributes.Private, mdr); md.Body = new MethodBody(md); md.Body.InitLocals = true; md.Body.Instructions.Clear(); foreach (Instruction ii in instructions) { if (ii.OpCode == OpCodes.Newobj) { md.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0)); md.Body.Instructions.Add(Instruction.Create(OpCodes.Call, assignNodeContext)); } md.Body.Instructions.Add(ii); } foreach (VariableDefinition l in this.m_Method.Body.Variables) { md.Body.Variables.Add(l); } foreach (ExceptionHandler ex in this.m_Method.Body.ExceptionHandlers) { md.Body.ExceptionHandlers.Add(ex); } foreach (ParameterDefinition p in this.m_Method.Parameters) { md.Parameters.Add(p); } foreach (GenericParameter gp in this.m_Method.GenericParameters) { GenericParameter gpn = new GenericParameter(gp.Name, md); gpn.Attributes = gp.Attributes; foreach (TypeReference tr in gp.Constraints) { gpn.Constraints.Add(tr); } md.GenericParameters.Add(gpn); } this.m_Type.Methods.Add(md); Utility.AddAttribute(md, typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute), this.m_Module); // Get the ILProcessor and create variables to store the delegate variable // and delegate constructor. ILProcessor il = this.m_Method.Body.GetILProcessor(); VariableDefinition vd; MethodReference ct; // Clear the existing instructions and local variables. this.m_Method.Body.ExceptionHandlers.Clear(); this.m_Method.Body.Instructions.Clear(); this.m_Method.Body.Variables.Clear(); // Generate the IL for the delegate definition and fill the vd and ct // variables. TypeDefinition dg = Utility.EmitDelegate(il, idc, md, this.m_Type, out vd, out ct); // Implement the Invoke method in the DirectInvoke class. this.ImplementDirectInvokeClass(idc, dg, md.Parameters, md.ReturnType); // Create the Process4.Providers.DpmEntrypoint::GetProperty method reference. MethodReference getproperty = new MethodReference("GetProperty", this.m_Type.Module.Import(typeof(object)), this.m_Type.Module.Import(typeof(DpmEntrypoint))); getproperty.Parameters.Add(new ParameterDefinition(this.m_Type.Module.Import(typeof(Delegate)))); getproperty.Parameters.Add(new ParameterDefinition(this.m_Type.Module.Import(typeof(object[])))); // Create the Process4.Providers.DpmEntrypoint::SetProperty method reference. MethodReference setproperty = new MethodReference("SetProperty", this.m_Type.Module.Import(typeof(object)), this.m_Type.Module.Import(typeof(DpmEntrypoint))); setproperty.Parameters.Add(new ParameterDefinition(this.m_Type.Module.Import(typeof(Delegate)))); setproperty.Parameters.Add(new ParameterDefinition(this.m_Type.Module.Import(typeof(object[])))); // Create the Process4.Providers.DpmEntrypoint::Invoke method reference. MethodReference invoke = new MethodReference("Invoke", this.m_Type.Module.Import(typeof(object)), this.m_Type.Module.Import(typeof(DpmEntrypoint))); invoke.Parameters.Add(new ParameterDefinition(this.m_Type.Module.Import(typeof(Delegate)))); invoke.Parameters.Add(new ParameterDefinition(this.m_Type.Module.Import(typeof(object[])))); // Generate the local variables like: // * 0 - MultitypeDelegate // * 1 - object[] // * 2 - {return type} (if not void) VariableDefinition v_0 = vd; VariableDefinition v_1 = new VariableDefinition(this.m_Type.Module.Import(typeof(object[]))); VariableDefinition v_2 = new VariableDefinition(md.ReturnType); // Add the variables to the local variable list (delegate is already added). this.m_Method.Body.Variables.Add(v_1); if (v_2.VariableType.Name.ToLower() != "void") { this.m_Method.Body.Variables.Add(v_2); } // Force local variables to be initalized. this.m_Method.Body.InitLocals = true; this.m_Method.Body.MaxStackSize = 10; // Create statement processor for method. StatementProcessor processor = new StatementProcessor(il); // Make a generic version of the delegate method. TypeDefinition btd = this.m_Type; MethodDefinition bmd = md; MethodReference bmr = btd.Module.Import(bmd); GenericInstanceType bti = null; if (this.m_Type.HasGenericParameters) { bti = (GenericInstanceType)Utility.MakeGenericType(this.m_Type, this.m_Type.GenericParameters.ToArray()); bmr = Utility.MakeGeneric(bmr, bti.GenericArguments.ToArray()); } if (this.m_Method.HasGenericParameters) { GenericInstanceMethod gim = new GenericInstanceMethod(bmr); foreach (GenericParameter gp in bmr.GenericParameters) { gim.GenericArguments.Add(gp); } bmr = gim; } foreach (var gp in this.m_Type.GenericParameters) { ((GenericInstanceType)ct.DeclaringType).GenericArguments.Add(gp); } foreach (var gp in this.m_Method.GenericParameters) { ((GenericInstanceType)ct.DeclaringType).GenericArguments.Add(gp); } // Initialize the delegate. processor.Add(new InitDelegateStatement(ct, bmr, v_0)); // Initialize the array. if (this.m_Method.IsSetter) { il.Append(Instruction.Create(OpCodes.Ldloc_0)); } processor.Add( new InitArrayStatement( this.m_Module.Import(typeof(object)), (sbyte)md.Parameters.Count, v_1, new Action <ILProcessor, int>((p, i) => { // Get a reference to the parameter being passed to the method. ParameterDefinition pd = this.m_Method.Parameters[i]; if (i > this.m_Method.Parameters.Count - 1) { return; } // Create IL to copy the value from the parameter directly // into the array, boxing the value if needed. p.Append(Instruction.Create(OpCodes.Ldloc, v_1)); p.Append(Instruction.Create(OpCodes.Ldc_I4_S, (sbyte)i)); p.Append(Instruction.Create(OpCodes.Ldarg_S, pd)); if (pd.ParameterType.IsValueType || pd.ParameterType.IsGenericParameter) { p.Append(Instruction.Create(OpCodes.Box, pd.ParameterType)); } p.Append(Instruction.Create(OpCodes.Stelem_Ref)); }))); // Call the delegate. if (this.m_Method.IsSetter) { processor.Add(new CallStatement(setproperty, new VariableDefinition[] { v_1 }, this.m_Method.ReturnType, v_2)); } else if (this.m_Method.IsGetter) { processor.Add(new CallStatement(getproperty, new VariableDefinition[] { v_0, v_1 }, this.m_Method.ReturnType, v_2)); } else { processor.Add(new CallStatement(invoke, new VariableDefinition[] { v_0, v_1 }, this.m_Method.ReturnType, v_2)); } }