Example #1
0
        /// <summary>
        /// Wraps the field.
        /// </summary>
        public void Wrap(WrapContext context)
        {
            // Throw an exception if it's not a compiler generated field.
            if (this.m_Field.CustomAttributes.Count(c => c.AttributeType.Name == "CompilerGeneratedAttribute") == 0 &&
                !this.IsEvent(this.m_Field.FieldType) &&
                !Utility.HasAttribute(this.m_Field.CustomAttributes, "LocalAttribute") &&
                !this.m_Field.IsLiteral)
            {
                throw new PostProcessingException(this.m_Type.FullName, this.m_Field.Name, "The field '" + this.m_Field.Name + "' was found.  Distributed types may not contain fields as they can not be hooked successfully.  Use auto-generated properties instead.");
            }

            if (this.IsEvent(this.m_Field.FieldType) &&
                !Utility.HasAttribute(this.m_Field.CustomAttributes, "LocalAttribute"))
            {
                throw new PostProcessingException(
                          this.m_Type.FullName,
                          this.m_Field.Name,
                          "Distributed events are no longer supported in version 3.");
            }

            // Apply the ProtoMember attribute if this is not a local field, constant or the Node field.
            if (this.m_Field.Name != "<Node>k__BackingField" &&
                !Utility.HasAttribute(this.m_Field.CustomAttributes, "LocalAttribute") &&
                !this.m_Field.IsLiteral)
            {
                Utility.AddProtoMemberAttribute(this.m_Field, ++context.ProtoMemberCount);
            }
        }
Example #2
0
        /// <summary>
        /// Wraps the method.
        /// </summary>
        public void Wrap(WrapContext context)
        {
            this.m_TraceSource.TraceEvent(TraceEventType.Information, 0, "Modifying {0} for distributed processing", this.m_Constructor.Name);

            // Create the Process4.Providers.DpmEntrypoint::Construct method reference.
            var construct = new MethodReference("Construct", this.m_Type.Module.Import(typeof(void)), this.m_Type.Module.Import(typeof(DpmEntrypoint)));

            construct.Parameters.Add(new ParameterDefinition(this.m_Type.Module.Import(typeof(object))));

            // It's technically not valid to call a method on this before the base constructor
            // has been called.  To ensure the code is valid, we find the call to the base constructor and place
            // our Construct call right after it.
            Instruction instr = null;

            for (var i = 0; i < this.m_Constructor.Body.Instructions.Count; i++)
            {
                instr = this.m_Constructor.Body.Instructions[i];
                if (instr.OpCode == OpCodes.Call &&
                    instr.Operand is MethodReference &&
                    ((MethodReference)instr.Operand).Name == ".ctor")
                {
                    break;
                }
            }

            // Prepend instructions.
            var il = this.m_Constructor.Body.GetILProcessor();

            il.InsertAfter(instr, Instruction.Create(OpCodes.Call, construct));
            il.InsertAfter(instr, Instruction.Create(OpCodes.Ldarg_0));
        }
Example #3
0
        /// <summary>
        /// Wraps the field.
        /// </summary>
        public void Wrap(WrapContext context)
        {
            // Throw an exception if it's not a compiler generated field.
            if (this.m_Field.CustomAttributes.Count(c => c.AttributeType.Name == "CompilerGeneratedAttribute") == 0 &&
                !this.IsEvent(this.m_Field.FieldType) &&
                !Utility.HasAttribute(this.m_Field.CustomAttributes, "LocalAttribute") &&
                !this.m_Field.IsLiteral)
                throw new PostProcessingException(this.m_Type.FullName, this.m_Field.Name, "The field '" + this.m_Field.Name + "' was found.  Distributed types may not contain fields as they can not be hooked successfully.  Use auto-generated properties instead.");

            if (this.IsEvent(this.m_Field.FieldType) &&
                !Utility.HasAttribute(this.m_Field.CustomAttributes, "LocalAttribute"))
            {
                throw new PostProcessingException(
                    this.m_Type.FullName,
                    this.m_Field.Name,
                    "Distributed events are no longer supported in version 3.");
            }

            // Apply the ProtoMember attribute if this is not a local field, constant or the Node field.
            if (this.m_Field.Name != "<Node>k__BackingField" &&
                !Utility.HasAttribute(this.m_Field.CustomAttributes, "LocalAttribute") &&
                !this.m_Field.IsLiteral)
            {
                Utility.AddProtoMemberAttribute(this.m_Field, ++context.ProtoMemberCount);
            }
        }
Example #4
0
        /// <summary>
        /// Wraps the method.
        /// </summary>
        public void Wrap(WrapContext context)
        {
            this.m_TraceSource.TraceEvent(TraceEventType.Information, 0, "Modifying {0} for distributed processing", this.m_Constructor.Name);

            // Create the Process4.Providers.DpmEntrypoint::Construct method reference.
            var construct = new MethodReference("Construct", this.m_Type.Module.Import(typeof(void)), this.m_Type.Module.Import(typeof(DpmEntrypoint)));
            construct.Parameters.Add(new ParameterDefinition(this.m_Type.Module.Import(typeof(object))));

            // It's technically not valid to call a method on this before the base constructor
            // has been called.  To ensure the code is valid, we find the call to the base constructor and place
            // our Construct call right after it.
            Instruction instr = null;
            for (var i = 0; i < this.m_Constructor.Body.Instructions.Count; i++)
            {
                instr = this.m_Constructor.Body.Instructions[i];
                if (instr.OpCode == OpCodes.Call &&
                    instr.Operand is MethodReference &&
                    ((MethodReference)instr.Operand).Name == ".ctor")
                {
                    break;
                }
            }

            // Prepend instructions.
            var il = this.m_Constructor.Body.GetILProcessor();
            il.InsertAfter(instr, Instruction.Create(OpCodes.Call, construct));
            il.InsertAfter(instr, Instruction.Create(OpCodes.Ldarg_0));
        }
Example #5
0
 /// <summary>
 /// Wraps the property.
 /// </summary>
 public void Wrap(WrapContext context)
 {
     // Check to ensure property type has a distributed attribute or is a value type.
     if (this.m_Property.PropertyType.Resolve() == null)
     {
         // Not sure what to do with this?
         var warning =
             "Property {0} has type {1} which does not resolve to a full type.  If this is a " +
             "generic type, ensure that the generic type is restricted to value types or other " +
             "distributed types.  If a non-distributed type is used, runtime exceptions may occur.";
         this.m_TraceSource.TraceEvent(
             TraceEventType.Warning,
             0,
             warning,
             this.m_Property.Name,
             this.m_Property.PropertyType.Name);
     }
     else if (this.m_Property.PropertyType.IsValueType ||
              this.m_Property.PropertyType.IsArray ||
              this.m_Property.PropertyType.Resolve().IsInterface ||
              this.m_Property.PropertyType.FullName == "System.String" ||
              Utility.HasAttribute(this.m_Property.PropertyType.Resolve(), "DistributedAttribute"))
     {
         // This is a valid type.
         this.m_TraceSource.TraceEvent(TraceEventType.Information, 0, "Recognised {0} as valid property", this.m_Property.Name);
     }
     else if (Utility.HasAttribute(this.m_Property.CustomAttributes, "LocalAttribute"))
     {
         // This is a localized property; add the get and set methods to our
         // exclusion list.
         this.m_TraceSource.TraceEvent(
             TraceEventType.Verbose,
             0,
             "Adding getter / setters of {0} to exclusions list because the property is marked with LocalAttribute",
             this.m_Property.Name);
         this.Exclusions.Add(this.m_Property.GetMethod.Name);
         this.Exclusions.Add(this.m_Property.SetMethod.Name);
     }
     else
     {
         // This is an invalid type (throw an exception).
         this.m_TraceSource.TraceEvent(TraceEventType.Error, 0, "Property {0} isn't of a valid type", this.m_Property.Name);
         throw new PostProcessingException(
                   this.m_Type.FullName,
                   this.m_Property.Name,
                   "The property '" + this.m_Property.Name + "' is of type '" + this.m_Property.PropertyType.Name + "', but it is not a distributed or value type.  Distributed types may only contain properties that are value types or types which are also distributed.");
     }
 }
Example #6
0
        public void Wrap(WrapContext context)
        {
            var synchronisedFieldsOrProperties = new List <FieldOrPropertyDefinition>();

            foreach (var property in this.m_Type.Properties)
            {
                if (Utility.HasAttribute(property.CustomAttributes, "SynchronisedAttribute"))
                {
                    synchronisedFieldsOrProperties.Add(new FieldOrPropertyDefinition {
                        Property = property, IsField = false
                    });
                }
            }
            foreach (var field in this.m_Type.Fields)
            {
                if (Utility.HasAttribute(field.CustomAttributes, "SynchronisedAttribute"))
                {
                    synchronisedFieldsOrProperties.Add(new FieldOrPropertyDefinition {
                        Field = field, IsField = true
                    });
                }
            }

            if (synchronisedFieldsOrProperties.Count == 0)
            {
                return;
            }

            this.m_TraceSource.TraceEvent(
                TraceEventType.Information,
                0,
                "Detected synchronisation attribute on one or more fields / properties of {0}",
                this.m_Type.FullName);

            // Mark as processed.
            this.m_TraceSource.TraceEvent(TraceEventType.Verbose, 0, "Adding ProcessedAttribute to {0}", this.m_Type.FullName);
            Utility.AddAttribute(this.m_Type, typeof(ProcessedAttribute), this.m_Type.Module);

            // Get a reference to the synchronisation store's constructor.
            var synchronisationStoreCtor = new MethodReference(
                ".ctor",
                this.m_Type.Module.Import(typeof(void)),
                this.m_Type.Module.Import(typeof(SynchronisationStore)));

            synchronisationStoreCtor.HasThis = true;

            // Generate nested class that inherits from SynchronisationStore.
            var nestedClass = this.m_TypeBuilder.CreateNestedClass(
                this.m_Type,
                string.Empty,
                this.m_Type.Name + "_SynchronisationStore",
                this.m_Type.Module.Import(typeof(SynchronisationStore)));

            // Add distributed attribute onto the nested class.
            nestedClass.CustomAttributes.Add(new CustomAttribute(
                                                 new MethodReference(
                                                     ".ctor",
                                                     this.m_Type.Module.Import(typeof(void)),
                                                     this.m_Type.Module.Import(typeof(DistributedAttribute)))
            {
                HasThis = true
            }));

            // Create copies of all synchronised properties in the synchronisation store.
            foreach (var prop in synchronisedFieldsOrProperties)
            {
                if (prop.IsField)
                {
                    Utility.AddAutoProperty(
                        nestedClass,
                        prop.Field.Name,
                        this.m_SynchronisationTypeTranslator.GetDistributedType(prop.Field.FieldType));
                }
                else
                {
                    Utility.AddAutoProperty(
                        nestedClass,
                        prop.Property.Name,
                        this.m_SynchronisationTypeTranslator.GetDistributedType(prop.Property.PropertyType));
                }
            }

            // Create default constructor.
            var ctor   = this.m_MethodBuilder.CreateConstructor(nestedClass);
            var ctorIL = ctor.Body.GetILProcessor();

            ctorIL.Append(Instruction.Create(OpCodes.Ldarg_0));
            ctorIL.Append(Instruction.Create(OpCodes.Call, synchronisationStoreCtor));
            ctorIL.Append(Instruction.Create(OpCodes.Ret));

            // Create overrides for GetNames and GetTypes.
            var getNames = this.m_MethodBuilder.CreateOverride(
                nestedClass,
                "GetNames",
                nestedClass.Module.Import(typeof(string[])));
            var getTypes = this.m_MethodBuilder.CreateOverride(
                nestedClass,
                "GetTypes",
                nestedClass.Module.Import(typeof(Type[])));
            var getIsFields = this.m_MethodBuilder.CreateOverride(
                nestedClass,
                "GetIsFields",
                nestedClass.Module.Import(typeof(bool[])));

            // Mark the methods as local so the distributed processor doesn't
            // intercept them at all.
            getNames.CustomAttributes.Add(new CustomAttribute(new MethodReference(
                                                                  ".ctor",
                                                                  this.m_Type.Module.Import(typeof(void)),
                                                                  this.m_Type.Module.Import(typeof(LocalAttribute)))
            {
                HasThis = true
            }));
            getTypes.CustomAttributes.Add(new CustomAttribute(new MethodReference(
                                                                  ".ctor",
                                                                  this.m_Type.Module.Import(typeof(void)),
                                                                  this.m_Type.Module.Import(typeof(LocalAttribute)))
            {
                HasThis = true
            }));
            getIsFields.CustomAttributes.Add(new CustomAttribute(new MethodReference(
                                                                     ".ctor",
                                                                     this.m_Type.Module.Import(typeof(void)),
                                                                     this.m_Type.Module.Import(typeof(LocalAttribute)))
            {
                HasThis = true
            }));

            // Emit opcodes to produce GetNames.
            getNames.Body.Variables.Add(new VariableDefinition(
                                            this.m_Type.Module.Import(typeof(string[]))));
            var getNamesIL = getNames.Body.GetILProcessor();

            getNamesIL.Append(Instruction.Create(OpCodes.Ldc_I4, synchronisedFieldsOrProperties.Count));
            getNamesIL.Append(Instruction.Create(OpCodes.Newarr, this.m_Type.Module.Import(typeof(string))));
            for (var i = 0; i < synchronisedFieldsOrProperties.Count; i++)
            {
                var name = synchronisedFieldsOrProperties[i].IsField ?
                           synchronisedFieldsOrProperties[i].Field.Name :
                           synchronisedFieldsOrProperties[i].Property.Name;
                getNamesIL.Append(Instruction.Create(OpCodes.Dup));
                getNamesIL.Append(Instruction.Create(OpCodes.Ldc_I4, i));
                getNamesIL.Append(Instruction.Create(OpCodes.Ldstr, name));
                getNamesIL.Append(Instruction.Create(OpCodes.Stelem_Ref));
            }
            getNamesIL.Append(Instruction.Create(OpCodes.Stloc_0));
            getNamesIL.Append(Instruction.Create(OpCodes.Ldloc_0));
            getNamesIL.Append(Instruction.Create(OpCodes.Ret));

            // Get a reference to the GetTypeFromHandle method, which is used for typeof().
            var getTypeFromHandle = new MethodReference(
                "GetTypeFromHandle",
                this.m_Type.Module.Import(typeof(Type)),
                this.m_Type.Module.Import(typeof(Type)));

            getTypeFromHandle.Parameters.Add(new ParameterDefinition(
                                                 this.m_Type.Module.Import(typeof(RuntimeTypeHandle))));

            // Emit opcodes to produce GetTypes.
            getTypes.Body.Variables.Add(new VariableDefinition(
                                            this.m_Type.Module.Import(typeof(Type[]))));
            var getTypesIL = getTypes.Body.GetILProcessor();

            getTypesIL.Append(Instruction.Create(OpCodes.Ldc_I4, synchronisedFieldsOrProperties.Count));
            getTypesIL.Append(Instruction.Create(OpCodes.Newarr, this.m_Type.Module.Import(typeof(Type))));
            for (var i = 0; i < synchronisedFieldsOrProperties.Count; i++)
            {
                var type = synchronisedFieldsOrProperties[i].IsField ?
                           synchronisedFieldsOrProperties[i].Field.FieldType :
                           synchronisedFieldsOrProperties[i].Property.PropertyType;
                getTypesIL.Append(Instruction.Create(OpCodes.Dup));
                getTypesIL.Append(Instruction.Create(OpCodes.Ldc_I4, i));
                getTypesIL.Append(Instruction.Create(OpCodes.Ldtoken, this.m_Type.Module.Import(type)));
                getTypesIL.Append(Instruction.Create(OpCodes.Call, getTypeFromHandle));
                getTypesIL.Append(Instruction.Create(OpCodes.Stelem_Ref));
            }
            getTypesIL.Append(Instruction.Create(OpCodes.Stloc_0));
            getTypesIL.Append(Instruction.Create(OpCodes.Ldloc_0));
            getTypesIL.Append(Instruction.Create(OpCodes.Ret));

            // Emit opcodes to produce GetNames.
            getIsFields.Body.Variables.Add(new VariableDefinition(
                                               this.m_Type.Module.Import(typeof(bool[]))));
            var getIsFieldsIL = getIsFields.Body.GetILProcessor();

            getIsFieldsIL.Append(Instruction.Create(OpCodes.Ldc_I4, synchronisedFieldsOrProperties.Count));
            getIsFieldsIL.Append(Instruction.Create(OpCodes.Newarr, this.m_Type.Module.Import(typeof(bool))));
            for (var i = 0; i < synchronisedFieldsOrProperties.Count; i++)
            {
                getIsFieldsIL.Append(Instruction.Create(OpCodes.Dup));
                getIsFieldsIL.Append(Instruction.Create(OpCodes.Ldc_I4, i));
                getIsFieldsIL.Append(Instruction.Create(OpCodes.Ldc_I4, synchronisedFieldsOrProperties[i].IsField ? 1 : 0));
                getIsFieldsIL.Append(Instruction.Create(OpCodes.Stelem_I1));
            }
            getIsFieldsIL.Append(Instruction.Create(OpCodes.Stloc_0));
            getIsFieldsIL.Append(Instruction.Create(OpCodes.Ldloc_0));
            getIsFieldsIL.Append(Instruction.Create(OpCodes.Ret));

            // Create the field on the original type to hold an instance of
            // the nested class.
            var syncField = new FieldDefinition(
                "<>_SynchronisationField",
                FieldAttributes.Private,
                nestedClass);

            syncField.CustomAttributes.Add(new CustomAttribute(new MethodReference(
                                                                   ".ctor",
                                                                   this.m_Type.Module.Import(typeof(void)),
                                                                   this.m_Type.Module.Import(typeof(CompilerGeneratedAttribute)))
            {
                HasThis = true
            }));
            this.m_Type.Fields.Add(syncField);

            // Implement the ISynchronised interface on the original class.
            var syncMethod = new MethodDefinition(
                "GetSynchronisationStore",
                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Final | MethodAttributes.Virtual,
                this.m_Type.Module.Import(typeof(SynchronisationStore)));

            syncMethod.Parameters.Add(new ParameterDefinition(
                                          this.m_Type.Module.Import(typeof(ILocalNode))));
            syncMethod.Parameters.Add(new ParameterDefinition(
                                          this.m_Type.Module.Import(typeof(string))));
            this.m_Type.Methods.Add(syncMethod);

            // Get a reference to Distributed<NestedClass> and it's constructor.
            var distributedClass       = this.m_Type.Module.Import(typeof(Distributed <>));
            var distributedNestedClass = new GenericInstanceType(distributedClass);

            distributedNestedClass.GenericArguments.Add(nestedClass);
            var distributedNestedCtor = new MethodReference(
                ".ctor",
                this.m_Type.Module.Import(typeof(void)),
                distributedNestedClass)
            {
                HasThis = true
            };

            distributedNestedCtor.Parameters.Add(new ParameterDefinition(
                                                     this.m_Type.Module.Import(typeof(ILocalNode))));
            distributedNestedCtor.Parameters.Add(new ParameterDefinition(
                                                     this.m_Type.Module.Import(typeof(string))));

            // Get a reference to the cast to convert it to back to it's original object.
            var distributedNestedCast = new MethodReference(
                "op_Implicit",
                distributedClass.GenericParameters[0],
                distributedNestedClass);

            distributedNestedCast.HasThis = false;
            var distributedNestedClassParam2 = new GenericInstanceType(this.m_Type.Module.Import(typeof(Distributed <>)));

            distributedNestedClassParam2.GenericArguments.Add(distributedClass.GenericParameters[0]);
            distributedNestedCast.Parameters.Add(new ParameterDefinition(distributedNestedClassParam2));

            // Implement the GetSynchronisationStore method.
            syncMethod.Body.Variables.Add(new VariableDefinition(nestedClass));
            var il = syncMethod.Body.GetILProcessor();

            il.Append(Instruction.Create(OpCodes.Ldarg_0));
            var beforeCheck = Instruction.Create(OpCodes.Ldfld, syncField);

            il.Append(beforeCheck);
            // Brtrue to be inserted here
            il.Append(Instruction.Create(OpCodes.Ldarg_0));
            il.Append(Instruction.Create(OpCodes.Ldarg_1));
            il.Append(Instruction.Create(OpCodes.Ldarg_2));
            il.Append(Instruction.Create(OpCodes.Newobj, distributedNestedCtor));
            il.Append(Instruction.Create(OpCodes.Call, distributedNestedCast));
            il.Append(Instruction.Create(OpCodes.Stfld, syncField));
            var skip = Instruction.Create(OpCodes.Ldarg_0);

            il.Append(skip);
            il.Append(Instruction.Create(OpCodes.Ldfld, syncField));
            il.Append(Instruction.Create(OpCodes.Ret));

            // Insert brtrue.
            il.InsertAfter(
                beforeCheck,
                Instruction.Create(OpCodes.Brtrue, skip));

            // Add interface.
            this.m_Type.Interfaces.Add(this.m_Type.Module.Import(typeof(ISynchronised)));

            // Finally, apply distributed processing to the nested class!
            this.m_TraceSource.TraceEvent(TraceEventType.Information, 0, "Starting processing of {0}", nestedClass.Name);
            new TypeWrapper(nestedClass).Wrap(new WrapContext(0));
            this.m_TraceSource.TraceEvent(TraceEventType.Information, 0, "Finished processing of {0}", nestedClass.Name);
        }
Example #7
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));
            }
        }
Example #8
0
        /// <summary>
        /// Wraps the type.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        public void Wrap(WrapContext context)
        {
            // Add attributes.
            this.m_TraceSource.TraceEvent(
                TraceEventType.Verbose,
                0,
                "Adding ProcessedAttribute to {0}",
                this.m_Type.FullName);
            Utility.AddAttribute(this.m_Type, typeof(ProcessedAttribute), this.m_Type.Module);

            // Add ProtoContract attribute.
            this.m_TraceSource.TraceEvent(
                TraceEventType.Verbose,
                0,
                "Adding ProtoContractAttribute to {0}",
                this.m_Type.FullName);
            var pc = Utility.AddAttribute(this.m_Type, typeof(ProtoContractAttribute), this.m_Type.Module);

            pc.Properties.Add(
                new CustomAttributeNamedArgument(
                    "SkipConstructor",
                    new CustomAttributeArgument(this.m_Module.Import(typeof(bool)), true)));

            // Add appropriate interfaces.
            this.m_TraceSource.TraceEvent(
                TraceEventType.Verbose,
                0,
                "Adding interface ITransparent to {0}",
                this.m_Type.FullName);
            this.m_Type.Interfaces.Add(this.m_Module.Import(typeof(ITransparent)));

            // Add required properties.
            this.m_TraceSource.TraceEvent(
                TraceEventType.Verbose,
                0,
                "Implementing auto-property NetworkName on {0}",
                this.m_Type.FullName);
            Utility.AddAutoProperty(this.m_Type, "NetworkName", typeof(string), ++context.ProtoMemberCount);
            this.m_TraceSource.TraceEvent(
                TraceEventType.Verbose,
                0,
                "Implementing auto-property Node on {0}",
                this.m_Type.FullName);
            Utility.AddAutoProperty(this.m_Type, "Node", typeof(ILocalNode));

            // Define a list of exclusions for wrapping.
            var exclusions = new List <string>
            {
                "NetworkName",
                "get_NetworkName",
                "set_NetworkName",
                "Node",
                "get_Node",
                "set_Node"
            };

            // Wrap all of our other properties, methods and fields.
            foreach (var p in this.m_Type.Properties.Where(value => !exclusions.Contains(value.Name)).ToList())
            {
                (new PropertyWrapper(p)
                {
                    Exclusions = exclusions
                }).Wrap(context);
            }

            foreach (var p in this.m_Type.Properties.Where(value => exclusions.Contains(value.Name)).ToList())
            {
                this.m_TraceSource.TraceEvent(
                    TraceEventType.Information,
                    0,
                    "Skipping property wrapping on {0} because it is an excluded property",
                    p.Name);
            }

            foreach (var m in
                     this.m_Type.Methods.Where(
                         value => !exclusions.Contains(value.Name) && !value.IsStatic && value.Name != ".ctor").ToList())
            {
                (new MethodWrapper(m)).Wrap(context);
            }

            foreach (var m in
                     this.m_Type.Methods.Where(
                         value => (exclusions.Contains(value.Name) || value.IsStatic) && value.Name != ".ctor").ToList())
            {
                this.m_TraceSource.TraceEvent(
                    TraceEventType.Information,
                    0,
                    "Skipping method wrapping on {0} because it is an excluded method",
                    m.Name);
            }

            foreach (var m in this.m_Type.Methods.Where(value => value.Name == ".ctor").ToList())
            {
                (new ConstructorWrapper(m)).Wrap(context);
            }

            foreach (var f in this.m_Type.Fields.ToList())
            {
                (new FieldWrapper(f)).Wrap(context);
            }
        }
Example #9
0
        /// <summary>
        /// Wraps the type.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        public void Wrap(WrapContext context)
        {
            // Add attributes.
            this.m_TraceSource.TraceEvent(
                TraceEventType.Verbose,
                0,
                "Adding ProcessedAttribute to {0}",
                this.m_Type.FullName);
            Utility.AddAttribute(this.m_Type, typeof(ProcessedAttribute), this.m_Type.Module);

            // Add ProtoContract attribute.
            this.m_TraceSource.TraceEvent(
                TraceEventType.Verbose,
                0,
                "Adding ProtoContractAttribute to {0}",
                this.m_Type.FullName);
            var pc = Utility.AddAttribute(this.m_Type, typeof(ProtoContractAttribute), this.m_Type.Module);
            pc.Properties.Add(
                new CustomAttributeNamedArgument(
                    "SkipConstructor",
                    new CustomAttributeArgument(this.m_Module.Import(typeof(bool)), true)));

            // Add appropriate interfaces.
            this.m_TraceSource.TraceEvent(
                TraceEventType.Verbose,
                0,
                "Adding interface ITransparent to {0}",
                this.m_Type.FullName);
            this.m_Type.Interfaces.Add(this.m_Module.Import(typeof(ITransparent)));

            // Add required properties.
            this.m_TraceSource.TraceEvent(
                TraceEventType.Verbose,
                0,
                "Implementing auto-property NetworkName on {0}",
                this.m_Type.FullName);
            Utility.AddAutoProperty(this.m_Type, "NetworkName", typeof(string), ++context.ProtoMemberCount);
            this.m_TraceSource.TraceEvent(
                TraceEventType.Verbose,
                0,
                "Implementing auto-property Node on {0}",
                this.m_Type.FullName);
            Utility.AddAutoProperty(this.m_Type, "Node", typeof(ILocalNode));

            // Define a list of exclusions for wrapping.
            var exclusions = new List<string>
            {
                "NetworkName",
                "get_NetworkName",
                "set_NetworkName",
                "Node",
                "get_Node",
                "set_Node"
            };

            // Wrap all of our other properties, methods and fields.
            foreach (var p in this.m_Type.Properties.Where(value => !exclusions.Contains(value.Name)).ToList())
            {
                (new PropertyWrapper(p) { Exclusions = exclusions }).Wrap(context);
            }

            foreach (var p in this.m_Type.Properties.Where(value => exclusions.Contains(value.Name)).ToList())
            {
                this.m_TraceSource.TraceEvent(
                    TraceEventType.Information,
                    0,
                    "Skipping property wrapping on {0} because it is an excluded property",
                    p.Name);
            }

            foreach (var m in
                this.m_Type.Methods.Where(
                    value => !exclusions.Contains(value.Name) && !value.IsStatic && value.Name != ".ctor").ToList())
            {
                (new MethodWrapper(m)).Wrap(context);
            }

            foreach (var m in
                this.m_Type.Methods.Where(
                    value => (exclusions.Contains(value.Name) || value.IsStatic) && value.Name != ".ctor").ToList())
            {
                this.m_TraceSource.TraceEvent(
                    TraceEventType.Information,
                    0,
                    "Skipping method wrapping on {0} because it is an excluded method",
                    m.Name);
            }

            foreach (var m in this.m_Type.Methods.Where(value => value.Name == ".ctor").ToList())
            {
                (new ConstructorWrapper(m)).Wrap(context);
            }

            foreach (var f in this.m_Type.Fields.ToList())
            {
                (new FieldWrapper(f)).Wrap(context);
            }
        }
Example #10
0
        public void Wrap(WrapContext context)
        {
            var synchronisedFieldsOrProperties = new List<FieldOrPropertyDefinition>();
            foreach (var property in this.m_Type.Properties)
            {
                if (Utility.HasAttribute(property.CustomAttributes, "SynchronisedAttribute"))
                {
                    synchronisedFieldsOrProperties.Add(new FieldOrPropertyDefinition { Property = property, IsField = false });
                }
            }
            foreach (var field in this.m_Type.Fields)
            {
                if (Utility.HasAttribute(field.CustomAttributes, "SynchronisedAttribute"))
                {
                    synchronisedFieldsOrProperties.Add(new FieldOrPropertyDefinition { Field = field, IsField = true });
                }
            }

            if (synchronisedFieldsOrProperties.Count == 0)
                return;

            this.m_TraceSource.TraceEvent(
                TraceEventType.Information,
                0,
                "Detected synchronisation attribute on one or more fields / properties of {0}",
                this.m_Type.FullName);

            // Mark as processed.
            this.m_TraceSource.TraceEvent(TraceEventType.Verbose, 0, "Adding ProcessedAttribute to {0}", this.m_Type.FullName);
            Utility.AddAttribute(this.m_Type, typeof(ProcessedAttribute), this.m_Type.Module);

            // Get a reference to the synchronisation store's constructor.
            var synchronisationStoreCtor = new MethodReference(
                ".ctor",
                this.m_Type.Module.Import(typeof(void)),
                this.m_Type.Module.Import(typeof(SynchronisationStore)));
            synchronisationStoreCtor.HasThis = true;

            // Generate nested class that inherits from SynchronisationStore.
            var nestedClass = this.m_TypeBuilder.CreateNestedClass(
                this.m_Type,
                string.Empty,
                this.m_Type.Name + "_SynchronisationStore",
                this.m_Type.Module.Import(typeof(SynchronisationStore)));

            // Add distributed attribute onto the nested class.
            nestedClass.CustomAttributes.Add(new CustomAttribute(
                new MethodReference(
                    ".ctor",
                    this.m_Type.Module.Import(typeof(void)),
                    this.m_Type.Module.Import(typeof(DistributedAttribute))) { HasThis = true }));

            // Create copies of all synchronised properties in the synchronisation store.
            foreach (var prop in synchronisedFieldsOrProperties)
            {
                if (prop.IsField)
                    Utility.AddAutoProperty(
                        nestedClass,
                        prop.Field.Name,
                        this.m_SynchronisationTypeTranslator.GetDistributedType(prop.Field.FieldType));
                else
                    Utility.AddAutoProperty(
                        nestedClass,
                        prop.Property.Name,
                        this.m_SynchronisationTypeTranslator.GetDistributedType(prop.Property.PropertyType));
            }

            // Create default constructor.
            var ctor = this.m_MethodBuilder.CreateConstructor(nestedClass);
            var ctorIL = ctor.Body.GetILProcessor();
            ctorIL.Append(Instruction.Create(OpCodes.Ldarg_0));
            ctorIL.Append(Instruction.Create(OpCodes.Call, synchronisationStoreCtor));
            ctorIL.Append(Instruction.Create(OpCodes.Ret));

            // Create overrides for GetNames and GetTypes.
            var getNames = this.m_MethodBuilder.CreateOverride(
                nestedClass,
                "GetNames",
                nestedClass.Module.Import(typeof(string[])));
            var getTypes = this.m_MethodBuilder.CreateOverride(
                nestedClass,
                "GetTypes",
                nestedClass.Module.Import(typeof(Type[])));
            var getIsFields = this.m_MethodBuilder.CreateOverride(
                nestedClass,
                "GetIsFields",
                nestedClass.Module.Import(typeof(bool[])));

            // Mark the methods as local so the distributed processor doesn't
            // intercept them at all.
            getNames.CustomAttributes.Add(new CustomAttribute(new MethodReference(
                ".ctor",
                this.m_Type.Module.Import(typeof(void)),
                this.m_Type.Module.Import(typeof(LocalAttribute))) { HasThis = true }));
            getTypes.CustomAttributes.Add(new CustomAttribute(new MethodReference(
                ".ctor",
                this.m_Type.Module.Import(typeof(void)),
                this.m_Type.Module.Import(typeof(LocalAttribute))) { HasThis = true }));
            getIsFields.CustomAttributes.Add(new CustomAttribute(new MethodReference(
                ".ctor",
                this.m_Type.Module.Import(typeof(void)),
                this.m_Type.Module.Import(typeof(LocalAttribute))) { HasThis = true }));

            // Emit opcodes to produce GetNames.
            getNames.Body.Variables.Add(new VariableDefinition(
                this.m_Type.Module.Import(typeof(string[]))));
            var getNamesIL = getNames.Body.GetILProcessor();
            getNamesIL.Append(Instruction.Create(OpCodes.Ldc_I4, synchronisedFieldsOrProperties.Count));
            getNamesIL.Append(Instruction.Create(OpCodes.Newarr, this.m_Type.Module.Import(typeof(string))));
            for (var i = 0; i < synchronisedFieldsOrProperties.Count; i++)
            {
                var name = synchronisedFieldsOrProperties[i].IsField ?
                    synchronisedFieldsOrProperties[i].Field.Name :
                    synchronisedFieldsOrProperties[i].Property.Name;
                getNamesIL.Append(Instruction.Create(OpCodes.Dup));
                getNamesIL.Append(Instruction.Create(OpCodes.Ldc_I4, i));
                getNamesIL.Append(Instruction.Create(OpCodes.Ldstr, name));
                getNamesIL.Append(Instruction.Create(OpCodes.Stelem_Ref));
            }
            getNamesIL.Append(Instruction.Create(OpCodes.Stloc_0));
            getNamesIL.Append(Instruction.Create(OpCodes.Ldloc_0));
            getNamesIL.Append(Instruction.Create(OpCodes.Ret));

            // Get a reference to the GetTypeFromHandle method, which is used for typeof().
            var getTypeFromHandle = new MethodReference(
                "GetTypeFromHandle",
                this.m_Type.Module.Import(typeof(Type)),
                this.m_Type.Module.Import(typeof(Type)));
            getTypeFromHandle.Parameters.Add(new ParameterDefinition(
                this.m_Type.Module.Import(typeof(RuntimeTypeHandle))));

            // Emit opcodes to produce GetTypes.
            getTypes.Body.Variables.Add(new VariableDefinition(
                this.m_Type.Module.Import(typeof(Type[]))));
            var getTypesIL = getTypes.Body.GetILProcessor();
            getTypesIL.Append(Instruction.Create(OpCodes.Ldc_I4, synchronisedFieldsOrProperties.Count));
            getTypesIL.Append(Instruction.Create(OpCodes.Newarr, this.m_Type.Module.Import(typeof(Type))));
            for (var i = 0; i < synchronisedFieldsOrProperties.Count; i++)
            {
                var type = synchronisedFieldsOrProperties[i].IsField ?
                    synchronisedFieldsOrProperties[i].Field.FieldType :
                    synchronisedFieldsOrProperties[i].Property.PropertyType;
                getTypesIL.Append(Instruction.Create(OpCodes.Dup));
                getTypesIL.Append(Instruction.Create(OpCodes.Ldc_I4, i));
                getTypesIL.Append(Instruction.Create(OpCodes.Ldtoken, this.m_Type.Module.Import(type)));
                getTypesIL.Append(Instruction.Create(OpCodes.Call, getTypeFromHandle));
                getTypesIL.Append(Instruction.Create(OpCodes.Stelem_Ref));
            }
            getTypesIL.Append(Instruction.Create(OpCodes.Stloc_0));
            getTypesIL.Append(Instruction.Create(OpCodes.Ldloc_0));
            getTypesIL.Append(Instruction.Create(OpCodes.Ret));

            // Emit opcodes to produce GetNames.
            getIsFields.Body.Variables.Add(new VariableDefinition(
                this.m_Type.Module.Import(typeof(bool[]))));
            var getIsFieldsIL = getIsFields.Body.GetILProcessor();
            getIsFieldsIL.Append(Instruction.Create(OpCodes.Ldc_I4, synchronisedFieldsOrProperties.Count));
            getIsFieldsIL.Append(Instruction.Create(OpCodes.Newarr, this.m_Type.Module.Import(typeof(bool))));
            for (var i = 0; i < synchronisedFieldsOrProperties.Count; i++)
            {
                getIsFieldsIL.Append(Instruction.Create(OpCodes.Dup));
                getIsFieldsIL.Append(Instruction.Create(OpCodes.Ldc_I4, i));
                getIsFieldsIL.Append(Instruction.Create(OpCodes.Ldc_I4, synchronisedFieldsOrProperties[i].IsField ? 1 : 0));
                getIsFieldsIL.Append(Instruction.Create(OpCodes.Stelem_I1));
            }
            getIsFieldsIL.Append(Instruction.Create(OpCodes.Stloc_0));
            getIsFieldsIL.Append(Instruction.Create(OpCodes.Ldloc_0));
            getIsFieldsIL.Append(Instruction.Create(OpCodes.Ret));

            // Create the field on the original type to hold an instance of
            // the nested class.
            var syncField = new FieldDefinition(
                "<>_SynchronisationField",
                FieldAttributes.Private,
                nestedClass);
            syncField.CustomAttributes.Add(new CustomAttribute(new MethodReference(
                ".ctor",
                this.m_Type.Module.Import(typeof(void)),
                this.m_Type.Module.Import(typeof(CompilerGeneratedAttribute))) { HasThis = true }));
            this.m_Type.Fields.Add(syncField);

            // Implement the ISynchronised interface on the original class.
            var syncMethod = new MethodDefinition(
                "GetSynchronisationStore",
                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Final | MethodAttributes.Virtual,
                this.m_Type.Module.Import(typeof(SynchronisationStore)));
            syncMethod.Parameters.Add(new ParameterDefinition(
                this.m_Type.Module.Import(typeof(ILocalNode))));
            syncMethod.Parameters.Add(new ParameterDefinition(
                this.m_Type.Module.Import(typeof(string))));
            this.m_Type.Methods.Add(syncMethod);

            // Get a reference to Distributed<NestedClass> and it's constructor.
            var distributedClass = this.m_Type.Module.Import(typeof(Distributed<>));
            var distributedNestedClass = new GenericInstanceType(distributedClass);
            distributedNestedClass.GenericArguments.Add(nestedClass);
            var distributedNestedCtor = new MethodReference(
                ".ctor",
                this.m_Type.Module.Import(typeof(void)),
                distributedNestedClass) { HasThis = true };
            distributedNestedCtor.Parameters.Add(new ParameterDefinition(
                this.m_Type.Module.Import(typeof(ILocalNode))));
            distributedNestedCtor.Parameters.Add(new ParameterDefinition(
                this.m_Type.Module.Import(typeof(string))));

            // Get a reference to the cast to convert it to back to it's original object.
            var distributedNestedCast = new MethodReference(
                "op_Implicit",
                distributedClass.GenericParameters[0],
                distributedNestedClass);
            distributedNestedCast.HasThis = false;
            var distributedNestedClassParam2 = new GenericInstanceType(this.m_Type.Module.Import(typeof(Distributed<>)));
            distributedNestedClassParam2.GenericArguments.Add(distributedClass.GenericParameters[0]);
            distributedNestedCast.Parameters.Add(new ParameterDefinition(distributedNestedClassParam2));

            // Implement the GetSynchronisationStore method.
            syncMethod.Body.Variables.Add(new VariableDefinition(nestedClass));
            var il = syncMethod.Body.GetILProcessor();

            il.Append(Instruction.Create(OpCodes.Ldarg_0));
            var beforeCheck = Instruction.Create(OpCodes.Ldfld, syncField);
            il.Append(beforeCheck);
            // Brtrue to be inserted here
            il.Append(Instruction.Create(OpCodes.Ldarg_0));
            il.Append(Instruction.Create(OpCodes.Ldarg_1));
            il.Append(Instruction.Create(OpCodes.Ldarg_2));
            il.Append(Instruction.Create(OpCodes.Newobj, distributedNestedCtor));
            il.Append(Instruction.Create(OpCodes.Call, distributedNestedCast));
            il.Append(Instruction.Create(OpCodes.Stfld, syncField));
            var skip = Instruction.Create(OpCodes.Ldarg_0);
            il.Append(skip);
            il.Append(Instruction.Create(OpCodes.Ldfld, syncField));
            il.Append(Instruction.Create(OpCodes.Ret));

            // Insert brtrue.
            il.InsertAfter(
                beforeCheck,
                Instruction.Create(OpCodes.Brtrue, skip));

            // Add interface.
            this.m_Type.Interfaces.Add(this.m_Type.Module.Import(typeof(ISynchronised)));

            // Finally, apply distributed processing to the nested class!
            this.m_TraceSource.TraceEvent(TraceEventType.Information, 0, "Starting processing of {0}", nestedClass.Name);
            new TypeWrapper(nestedClass).Wrap(new WrapContext(0));
            this.m_TraceSource.TraceEvent(TraceEventType.Information, 0, "Finished processing of {0}", nestedClass.Name);
        }
Example #11
0
 /// <summary>
 /// Wraps the property.
 /// </summary>
 public void Wrap(WrapContext context)
 {
     // Check to ensure property type has a distributed attribute or is a value type.
     if (this.m_Property.PropertyType.Resolve() == null)
     {
         // Not sure what to do with this?
         var warning =
             "Property {0} has type {1} which does not resolve to a full type.  If this is a " +
             "generic type, ensure that the generic type is restricted to value types or other " +
             "distributed types.  If a non-distributed type is used, runtime exceptions may occur.";
         this.m_TraceSource.TraceEvent(
             TraceEventType.Warning,
             0,
             warning,
             this.m_Property.Name,
             this.m_Property.PropertyType.Name);
     }
     else if (this.m_Property.PropertyType.IsValueType ||
         this.m_Property.PropertyType.IsArray ||
         this.m_Property.PropertyType.Resolve().IsInterface ||
         this.m_Property.PropertyType.FullName == "System.String" ||
         Utility.HasAttribute(this.m_Property.PropertyType.Resolve(), "DistributedAttribute"))
     {
         // This is a valid type.
         this.m_TraceSource.TraceEvent(TraceEventType.Information, 0, "Recognised {0} as valid property", this.m_Property.Name);
     }
     else if (Utility.HasAttribute(this.m_Property.CustomAttributes, "LocalAttribute"))
     {
         // This is a localized property; add the get and set methods to our
         // exclusion list.
         this.m_TraceSource.TraceEvent(
             TraceEventType.Verbose,
             0,
             "Adding getter / setters of {0} to exclusions list because the property is marked with LocalAttribute",
             this.m_Property.Name);
         this.Exclusions.Add(this.m_Property.GetMethod.Name);
         this.Exclusions.Add(this.m_Property.SetMethod.Name);
     }
     else
     {
         // This is an invalid type (throw an exception).
         this.m_TraceSource.TraceEvent(TraceEventType.Error, 0, "Property {0} isn't of a valid type", this.m_Property.Name);
         throw new PostProcessingException(
             this.m_Type.FullName,
             this.m_Property.Name,
             "The property '" + this.m_Property.Name + "' is of type '" + this.m_Property.PropertyType.Name + "', but it is not a distributed or value type.  Distributed types may only contain properties that are value types or types which are also distributed.");
     }
 }
Example #12
0
        /// <summary>
        /// Called when the MSBuild task executes.  Also invoked by Program.Main
        /// when run from the command-line.
        /// </summary>
        /// <returns>Whether the build task succeeded.</returns>
        public bool Execute()
        {
            var kernel = new StandardKernel();
            kernel.Load<DxProcessNinjectModule>();
            var wrapperFactory = kernel.Get<IWrapperFactory>();

            Directory.SetCurrentDirectory(Path.GetDirectoryName(this.AssemblyFile));

            var source = new TraceSource("Processor", SourceLevels.All);
            source.TraceEvent(TraceEventType.Information, 0, "Processor started at {0:G}", DateTime.Now);

            try
            {
                // Get the assembly based on the path.
                AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(
                    Path.GetFileName(this.AssemblyFile),
                    new ReaderParameters
                    {
                        ReadSymbols = File.Exists(this.AssemblyFile + ".mdb") || File.Exists(this.AssemblyFile.Substring(0, this.AssemblyFile.Length - 4) + ".pdb"),
                    });

                // Get all of the types in the assembly.
                TypeDefinition[] types = assembly.MainModule.Types.ToArray();
                foreach (TypeDefinition type in types)
                {
                    // Skip the module and Program classes.
                    if (type.Name == "<Module>" || type.Name == "Program")
                    {
                        source.TraceEvent(TraceEventType.Information, 0, "Skipped {0} because it is a module", type.Name);
                        continue;
                    }

                    // Check to see whether this type has a ProcessedAttribute
                    // attached to it.
                    if (Utility.HasAttributeSpecific(type, "ProcessedAttribute"))
                    {
                        source.TraceEvent(TraceEventType.Information, 0, "Skipped {0} because it has already been processed", type.Name);
                        continue;
                    }

                    var context = new WrapContext(0);

                    // Apply synchronisation wrapper.
                    wrapperFactory.CreateSynchronisationWrapper(type).Wrap(context);

                    // Check to see whether this type has a DistributedAttribute
                    // attached to it.
                    if (!Utility.HasAttribute(type, "DistributedAttribute"))
                    {
                        source.TraceEvent(TraceEventType.Information, 0, "Skipped {0} because it does not have DistributedAttribute", type.Name);
                        continue;
                    }

                    // This type is marked as distributed, so we need to perform
                    // wrapping on it.
                    source.TraceEvent(TraceEventType.Information, 0, "Starting processing of {0}", type.Name);
                    new TypeWrapper(type).Wrap(context);
                    source.TraceEvent(TraceEventType.Information, 0, "Finished processing of {0}", type.Name);
                }

                assembly.Write(Path.GetFileName(this.AssemblyFile), new WriterParameters { WriteSymbols = true });
                source.TraceEvent(TraceEventType.Information, 0, "Processor completed successfully at {0:G}", DateTime.Now);

                return true;
            }
            catch (PostProcessingException e)
            {
                source.TraceEvent(
                    TraceEventType.Critical,
                    0,
            @"Post Processing Exception Occurred!
            {0} in {1} caused:
            {2}
            {3}
            {4}",
                    e.OffendingMember,
                    e.OffendingType,
                    e.GetType().FullName,
                    e.Message,
                    e.StackTrace);
                source.TraceEvent(TraceEventType.Stop, 0, "Processor failed at {0:G}", DateTime.Now);
                if (this.BuildEngine != null)
                    this.BuildEngine.LogErrorEvent(new BuildErrorEventArgs("Post Processing", "E0002", e.OffendingType + "." + e.OffendingMember, 0, 0, 0, 0, e.Message, "", ""));
                return false;
            }
            catch (Exception e)
            {
                source.TraceEvent(
                    TraceEventType.Critical,
                    0,
            @"Exception Occurred!
            {0}
            {1}
            {2}",
                    e.GetType().FullName,
                    e.Message,
                    e.StackTrace);
                source.TraceEvent(TraceEventType.Stop, 0, "Processor failed at {0:G}", DateTime.Now);
                if (this.BuildEngine != null)
                    this.BuildEngine.LogErrorEvent(new BuildErrorEventArgs("General", "E0001", "", 0, 0, 0, 0, e.Message, "", ""));
                return false;
            }
        }
Example #13
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));
            }
        }
Example #14
0
        /// <summary>
        /// Called when the MSBuild task executes.  Also invoked by Program.Main
        /// when run from the command-line.
        /// </summary>
        /// <returns>Whether the build task succeeded.</returns>
        public bool Execute()
        {
            var kernel = new StandardKernel();

            kernel.Load <DxProcessNinjectModule>();
            var wrapperFactory = kernel.Get <IWrapperFactory>();

            Directory.SetCurrentDirectory(Path.GetDirectoryName(this.AssemblyFile));

            var source = new TraceSource("Processor", SourceLevels.All);

            source.TraceEvent(TraceEventType.Information, 0, "Processor started at {0:G}", DateTime.Now);

            try
            {
                // Get the assembly based on the path.
                AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(
                    Path.GetFileName(this.AssemblyFile),
                    new ReaderParameters
                {
                    ReadSymbols = File.Exists(this.AssemblyFile + ".mdb") || File.Exists(this.AssemblyFile.Substring(0, this.AssemblyFile.Length - 4) + ".pdb"),
                });

                // Get all of the types in the assembly.
                TypeDefinition[] types = assembly.MainModule.Types.ToArray();
                foreach (TypeDefinition type in types)
                {
                    // Skip the module and Program classes.
                    if (type.Name == "<Module>" || type.Name == "Program")
                    {
                        source.TraceEvent(TraceEventType.Information, 0, "Skipped {0} because it is a module", type.Name);
                        continue;
                    }

                    // Check to see whether this type has a ProcessedAttribute
                    // attached to it.
                    if (Utility.HasAttributeSpecific(type, "ProcessedAttribute"))
                    {
                        source.TraceEvent(TraceEventType.Information, 0, "Skipped {0} because it has already been processed", type.Name);
                        continue;
                    }

                    var context = new WrapContext(0);

                    // Apply synchronisation wrapper.
                    wrapperFactory.CreateSynchronisationWrapper(type).Wrap(context);

                    // Check to see whether this type has a DistributedAttribute
                    // attached to it.
                    if (!Utility.HasAttribute(type, "DistributedAttribute"))
                    {
                        source.TraceEvent(TraceEventType.Information, 0, "Skipped {0} because it does not have DistributedAttribute", type.Name);
                        continue;
                    }

                    // This type is marked as distributed, so we need to perform
                    // wrapping on it.
                    source.TraceEvent(TraceEventType.Information, 0, "Starting processing of {0}", type.Name);
                    new TypeWrapper(type).Wrap(context);
                    source.TraceEvent(TraceEventType.Information, 0, "Finished processing of {0}", type.Name);
                }

                assembly.Write(Path.GetFileName(this.AssemblyFile), new WriterParameters {
                    WriteSymbols = true
                });
                source.TraceEvent(TraceEventType.Information, 0, "Processor completed successfully at {0:G}", DateTime.Now);

                return(true);
            }
            catch (PostProcessingException e)
            {
                source.TraceEvent(
                    TraceEventType.Critical,
                    0,
                    @"Post Processing Exception Occurred!
{0} in {1} caused:
{2}
{3}
{4}",
                    e.OffendingMember,
                    e.OffendingType,
                    e.GetType().FullName,
                    e.Message,
                    e.StackTrace);
                source.TraceEvent(TraceEventType.Stop, 0, "Processor failed at {0:G}", DateTime.Now);
                if (this.BuildEngine != null)
                {
                    this.BuildEngine.LogErrorEvent(new BuildErrorEventArgs("Post Processing", "E0002", e.OffendingType + "." + e.OffendingMember, 0, 0, 0, 0, e.Message, "", ""));
                }
                return(false);
            }
            catch (Exception e)
            {
                source.TraceEvent(
                    TraceEventType.Critical,
                    0,
                    @"Exception Occurred!
{0}
{1}
{2}",
                    e.GetType().FullName,
                    e.Message,
                    e.StackTrace);
                source.TraceEvent(TraceEventType.Stop, 0, "Processor failed at {0:G}", DateTime.Now);
                if (this.BuildEngine != null)
                {
                    this.BuildEngine.LogErrorEvent(new BuildErrorEventArgs("General", "E0001", "", 0, 0, 0, 0, e.Message, "", ""));
                }
                return(false);
            }
        }