Ejemplo n.º 1
0
        /// <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));
            }
        }
Ejemplo n.º 2
0
        /// <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));
            }
        }