/// <summary>
 /// 创建构造方法参数表达式树集合
 /// </summary>
 /// <param name="constructor"></param>
 /// <returns></returns>
 private IEnumerable<Expression> GetConstructorParameters(ConstructorInfo constructor, ParameterExpression parameter)
 {
     
     return constructor.GetParameterTypes().Select((parameterType, index) =>
            Expression.Convert(Expression.ArrayIndex(
                parameter, Expression.Constant(index)),
                parameterType));
 }
Example #2
0
        public virtual void Emit(OpCode opcode, ConstructorInfo con)
        {
            if (con == null)
                throw new ArgumentNullException("con");
            Contract.EndContractBlock();

            int stackchange = 0;

            // Constructors cannot be generic so the value of UseMethodDef doesn't matter.
            int tk = GetMethodToken(con, null, true);

            EnsureCapacity(7);
            InternalEmit(opcode);

            // Make a conservative estimate by assuming a return type and no
            // this parameter.
            if (opcode.StackBehaviourPush == StackBehaviour.Varpush)
            {
                // Instruction must be one of call or callvirt.
                Contract.Assert(opcode.Equals(OpCodes.Call) ||
                                opcode.Equals(OpCodes.Callvirt),
                                "Unexpected opcode encountered for StackBehaviour of VarPush.");
                stackchange++;
            }
            if (opcode.StackBehaviourPop == StackBehaviour.Varpop)
            {
                // Instruction must be one of call, callvirt or newobj.
                Contract.Assert(opcode.Equals(OpCodes.Call) ||
                                opcode.Equals(OpCodes.Callvirt) ||
                                opcode.Equals(OpCodes.Newobj),
                                "Unexpected opcode encountered for StackBehaviour of VarPop.");

                Type[] parameters = con.GetParameterTypes();
                if (parameters != null)
                    stackchange -= parameters.Length;
            }
            UpdateStackSize(opcode, stackchange);

            RecordTokenFixup();
            PutInteger4(tk);
        }
        internal void InitCustomAttributeBuilder(ConstructorInfo con, Object[] constructorArgs,
                                                 PropertyInfo[] namedProperties, Object[] propertyValues,
                                                 FieldInfo[] namedFields, Object[] fieldValues)
        {
            if (con == null)
                throw new ArgumentNullException(nameof(con));
            if (constructorArgs == null)
                throw new ArgumentNullException(nameof(constructorArgs));
            if (namedProperties == null)
                throw new ArgumentNullException(nameof(namedProperties));
            if (propertyValues == null)
                throw new ArgumentNullException(nameof(propertyValues));
            if (namedFields == null)
                throw new ArgumentNullException(nameof(namedFields));
            if (fieldValues == null)
                throw new ArgumentNullException(nameof(fieldValues));
            if (namedProperties.Length != propertyValues.Length)
                throw new ArgumentException(Environment.GetResourceString("Arg_ArrayLengthsDiffer"), "namedProperties, propertyValues");
            if (namedFields.Length != fieldValues.Length)
                throw new ArgumentException(Environment.GetResourceString("Arg_ArrayLengthsDiffer"), "namedFields, fieldValues");
            Contract.EndContractBlock();

            if ((con.Attributes & MethodAttributes.Static) == MethodAttributes.Static ||
                (con.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private)
                throw new ArgumentException(Environment.GetResourceString("Argument_BadConstructor"));

            if ((con.CallingConvention & CallingConventions.Standard) != CallingConventions.Standard)
                throw new ArgumentException(Environment.GetResourceString("Argument_BadConstructorCallConv"));

            // Cache information used elsewhere.
            m_con = con;
            m_constructorArgs = new Object[constructorArgs.Length];
            Array.Copy(constructorArgs, 0, m_constructorArgs, 0, constructorArgs.Length);

            Type[] paramTypes;
            int i;

            // Get the types of the constructor's formal parameters.
            paramTypes = con.GetParameterTypes();

            // Since we're guaranteed a non-var calling convention, the number of arguments must equal the number of parameters.
            if (paramTypes.Length != constructorArgs.Length)
                throw new ArgumentException(Environment.GetResourceString("Argument_BadParameterCountsForConstructor"));

            // Verify that the constructor has a valid signature (custom attributes only support a subset of our type system).
            for (i = 0; i < paramTypes.Length; i++)
                if (!ValidateType(paramTypes[i]))
                    throw new ArgumentException(Environment.GetResourceString("Argument_BadTypeInCustomAttribute"));

            // Now verify that the types of the actual parameters are compatible with the types of the formal parameters.
            for (i = 0; i < paramTypes.Length; i++)
            {
                object constructorArg = constructorArgs[i];
                if (constructorArg == null)
                {
                    if (paramTypes[i].IsValueType)
                    {
                        throw new ArgumentNullException($"{nameof(constructorArgs)}[{i}]");
                    }
                    continue;
                }
                VerifyTypeAndPassedObjectType(paramTypes[i], constructorArg.GetType(), $"{nameof(constructorArgs)}[{i}]");
            }

            // Allocate a memory stream to represent the CA blob in the metadata and a binary writer to help format it.
            MemoryStream stream = new MemoryStream();
            BinaryWriter writer = new BinaryWriter(stream);

            // Write the blob protocol version (currently 1).
            writer.Write((ushort)1);

            // Now emit the constructor argument values (no need for types, they're inferred from the constructor signature).
            for (i = 0; i < constructorArgs.Length; i++)
                EmitValue(writer, paramTypes[i], constructorArgs[i]);

            // Next a short with the count of properties and fields.
            writer.Write((ushort)(namedProperties.Length + namedFields.Length));

            // Emit all the property sets.
            for (i = 0; i < namedProperties.Length; i++)
            {
                // Validate the property.
                PropertyInfo property = namedProperties[i];
                if (property == null)
                    throw new ArgumentNullException("namedProperties[" + i + "]");

                // Allow null for non-primitive types only.
                Type propType = property.PropertyType;
                object propertyValue = propertyValues[i];
                if (propertyValue == null && propType.IsValueType)
                    throw new ArgumentNullException("propertyValues[" + i + "]");

                // Validate property type.
                if (!ValidateType(propType))
                    throw new ArgumentException(Environment.GetResourceString("Argument_BadTypeInCustomAttribute"));

                // Property has to be writable.
                if (!property.CanWrite)
                    throw new ArgumentException(Environment.GetResourceString("Argument_NotAWritableProperty"));

                // Property has to be from the same class or base class as ConstructorInfo.
                if (property.DeclaringType != con.DeclaringType
                    && (!(con.DeclaringType is TypeBuilderInstantiation))
                    && !con.DeclaringType.IsSubclassOf(property.DeclaringType))
                {
                    // Might have failed check because one type is a XXXBuilder
                    // and the other is not. Deal with these special cases
                    // separately.
                    if (!TypeBuilder.IsTypeEqual(property.DeclaringType, con.DeclaringType))
                    {
                        // IsSubclassOf is overloaded to do the right thing if
                        // the constructor is a TypeBuilder, but we still need
                        // to deal with the case where the property's declaring
                        // type is one.
                        if (!(property.DeclaringType is TypeBuilder) ||
                            !con.DeclaringType.IsSubclassOf(((TypeBuilder)property.DeclaringType).BakedRuntimeType))
                            throw new ArgumentException(Environment.GetResourceString("Argument_BadPropertyForConstructorBuilder"));
                    }
                }

                // Make sure the property's type can take the given value.
                // Note that there will be no coersion.
                if (propertyValue != null)
                {
                    VerifyTypeAndPassedObjectType(propType, propertyValue.GetType(), $"{nameof(propertyValues)}[{i}]");
                }

                // First a byte indicating that this is a property.
                writer.Write((byte)CustomAttributeEncoding.Property);

                // Emit the property type, name and value.
                EmitType(writer, propType);
                EmitString(writer, namedProperties[i].Name);
                EmitValue(writer, propType, propertyValue);
            }

            // Emit all the field sets.
            for (i = 0; i < namedFields.Length; i++)
            {
                // Validate the field.
                FieldInfo namedField = namedFields[i];
                if (namedField == null)
                    throw new ArgumentNullException("namedFields[" + i + "]");

                // Allow null for non-primitive types only.
                Type fldType = namedField.FieldType;
                object fieldValue = fieldValues[i];
                if (fieldValue == null && fldType.IsValueType)
                    throw new ArgumentNullException("fieldValues[" + i + "]");

                // Validate field type.
                if (!ValidateType(fldType))
                    throw new ArgumentException(Environment.GetResourceString("Argument_BadTypeInCustomAttribute"));

                // Field has to be from the same class or base class as ConstructorInfo.
                if (namedField.DeclaringType != con.DeclaringType
                    && (!(con.DeclaringType is TypeBuilderInstantiation))
                    && !con.DeclaringType.IsSubclassOf(namedField.DeclaringType))
                {
                    // Might have failed check because one type is a XXXBuilder
                    // and the other is not. Deal with these special cases
                    // separately.
                    if (!TypeBuilder.IsTypeEqual(namedField.DeclaringType, con.DeclaringType))
                    {
                        // IsSubclassOf is overloaded to do the right thing if
                        // the constructor is a TypeBuilder, but we still need
                        // to deal with the case where the field's declaring
                        // type is one.
                        if (!(namedField.DeclaringType is TypeBuilder) ||
                            !con.DeclaringType.IsSubclassOf(((TypeBuilder)namedFields[i].DeclaringType).BakedRuntimeType))
                            throw new ArgumentException(Environment.GetResourceString("Argument_BadFieldForConstructorBuilder"));
                    }
                }

                // Make sure the field's type can take the given value.
                // Note that there will be no coersion.
                if (fieldValue != null)
                {
                    VerifyTypeAndPassedObjectType(fldType, fieldValue.GetType(), $"{nameof(fieldValues)}[{i}]");
                }
                
                // First a byte indicating that this is a field.
                writer.Write((byte)CustomAttributeEncoding.Field);

                // Emit the field type, name and value.
                EmitType(writer, fldType);
                EmitString(writer, namedField.Name);
                EmitValue(writer, fldType, fieldValue);
            }

            // Create the blob array.
            m_blob = ((MemoryStream)writer.BaseStream).ToArray();
        }
        /// <summary>
        /// Defines a constructor based on the specified constructor.
        /// </summary>
        /// <param name="typeBuilder">The type builder.</param>
        /// <param name="constructorInfo">The constructor information.</param>
        /// <param name="additionalParameterTypes">The additional parameter types.</param>
        /// <param name="additionalParameterNames">The additional parameter names.</param>
        /// <returns>The constructor builder.</returns>
        public static ConstructorBuilder DefineConstructor(this TypeBuilder typeBuilder,
                                                           ConstructorInfo constructorInfo,
                                                           IEnumerable<Type> additionalParameterTypes,
                                                           IEnumerable<string> additionalParameterNames)
        {
            if (typeBuilder == null)
                throw new ArgumentNullException("typeBuilder");

            if (constructorInfo == null)
                throw new ArgumentNullException("constructorInfo");

            if (additionalParameterTypes == null)
                throw new ArgumentNullException("additionalParameterTypes");

            if (additionalParameterNames == null)
                throw new ArgumentNullException("additionalParameterNames");

            var methodAttributes = MethodAttributes.Public |
                                   constructorInfo.Attributes & (MethodAttributes.HideBySig |
                                                                 MethodAttributes.SpecialName |
                                                                 MethodAttributes.ReservedMask);
            var parameterTypes = new List<Type>();

            parameterTypes.AddRange(additionalParameterTypes);

            var parentParameterTypes = constructorInfo.GetParameterTypes();

            parameterTypes.AddRange(parentParameterTypes);

            // Define constructor.
            var constructorBuilder = typeBuilder.DefineConstructor(
                methodAttributes,
                constructorInfo.CallingConvention,
                parameterTypes.ToArray());

            // Define constructor parameters.
            constructorBuilder.DefineParameters(constructorInfo, additionalParameterNames);

            return constructorBuilder;
        }
 public virtual void Emit(OpCode opcode, ConstructorInfo con)
 {
     if (con == null)
     {
         throw new ArgumentNullException("con");
     }
     int stackchange = 0;
     int num2 = this.GetMethodToken(con, null, true);
     this.EnsureCapacity(7);
     this.InternalEmit(opcode);
     if (opcode.m_push == StackBehaviour.Varpush)
     {
         stackchange++;
     }
     if (opcode.m_pop == StackBehaviour.Varpop)
     {
         Type[] parameterTypes = con.GetParameterTypes();
         if (parameterTypes != null)
         {
             stackchange -= parameterTypes.Length;
         }
     }
     this.UpdateStackSize(opcode, stackchange);
     this.RecordTokenFixup();
     this.PutInteger4(num2);
 }
 internal void InitCustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues, FieldInfo[] namedFields, object[] fieldValues)
 {
     int num;
     if (con == null)
     {
         throw new ArgumentNullException("con");
     }
     if (constructorArgs == null)
     {
         throw new ArgumentNullException("constructorArgs");
     }
     if (namedProperties == null)
     {
         throw new ArgumentNullException("namedProperties");
     }
     if (propertyValues == null)
     {
         throw new ArgumentNullException("propertyValues");
     }
     if (namedFields == null)
     {
         throw new ArgumentNullException("namedFields");
     }
     if (fieldValues == null)
     {
         throw new ArgumentNullException("fieldValues");
     }
     if (namedProperties.Length != propertyValues.Length)
     {
         throw new ArgumentException(Environment.GetResourceString("Arg_ArrayLengthsDiffer"), "namedProperties, propertyValues");
     }
     if (namedFields.Length != fieldValues.Length)
     {
         throw new ArgumentException(Environment.GetResourceString("Arg_ArrayLengthsDiffer"), "namedFields, fieldValues");
     }
     if (((con.Attributes & MethodAttributes.Static) == MethodAttributes.Static) || ((con.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private))
     {
         throw new ArgumentException(Environment.GetResourceString("Argument_BadConstructor"));
     }
     if ((con.CallingConvention & CallingConventions.Standard) != CallingConventions.Standard)
     {
         throw new ArgumentException(Environment.GetResourceString("Argument_BadConstructorCallConv"));
     }
     this.m_con = con;
     this.m_constructorArgs = new object[constructorArgs.Length];
     Array.Copy(constructorArgs, this.m_constructorArgs, constructorArgs.Length);
     Type[] parameterTypes = con.GetParameterTypes();
     if (parameterTypes.Length != constructorArgs.Length)
     {
         throw new ArgumentException(Environment.GetResourceString("Argument_BadParameterCountsForConstructor"));
     }
     for (num = 0; num < parameterTypes.Length; num++)
     {
         if (!this.ValidateType(parameterTypes[num]))
         {
             throw new ArgumentException(Environment.GetResourceString("Argument_BadTypeInCustomAttribute"));
         }
     }
     for (num = 0; num < parameterTypes.Length; num++)
     {
         if (constructorArgs[num] != null)
         {
             TypeCode typeCode = Type.GetTypeCode(parameterTypes[num]);
             if ((typeCode != Type.GetTypeCode(constructorArgs[num].GetType())) && ((typeCode != TypeCode.Object) || !this.ValidateType(constructorArgs[num].GetType())))
             {
                 throw new ArgumentException(Environment.GetResourceString("Argument_BadParameterTypeForConstructor", new object[] { num }));
             }
         }
     }
     MemoryStream output = new MemoryStream();
     BinaryWriter writer = new BinaryWriter(output);
     writer.Write((ushort) 1);
     for (num = 0; num < constructorArgs.Length; num++)
     {
         this.EmitValue(writer, parameterTypes[num], constructorArgs[num]);
     }
     writer.Write((ushort) (namedProperties.Length + namedFields.Length));
     for (num = 0; num < namedProperties.Length; num++)
     {
         if (namedProperties[num] == null)
         {
             throw new ArgumentNullException("namedProperties[" + num + "]");
         }
         Type propertyType = namedProperties[num].PropertyType;
         if ((propertyValues[num] == null) && propertyType.IsPrimitive)
         {
             throw new ArgumentNullException("propertyValues[" + num + "]");
         }
         if (!this.ValidateType(propertyType))
         {
             throw new ArgumentException(Environment.GetResourceString("Argument_BadTypeInCustomAttribute"));
         }
         if (!namedProperties[num].CanWrite)
         {
             throw new ArgumentException(Environment.GetResourceString("Argument_NotAWritableProperty"));
         }
         if ((((namedProperties[num].DeclaringType != con.DeclaringType) && !(con.DeclaringType is TypeBuilderInstantiation)) && (!con.DeclaringType.IsSubclassOf(namedProperties[num].DeclaringType) && !TypeBuilder.IsTypeEqual(namedProperties[num].DeclaringType, con.DeclaringType))) && (!(namedProperties[num].DeclaringType is TypeBuilder) || !con.DeclaringType.IsSubclassOf(((TypeBuilder) namedProperties[num].DeclaringType).m_runtimeType)))
         {
             throw new ArgumentException(Environment.GetResourceString("Argument_BadPropertyForConstructorBuilder"));
         }
         if (((propertyValues[num] != null) && (propertyType != typeof(object))) && (Type.GetTypeCode(propertyValues[num].GetType()) != Type.GetTypeCode(propertyType)))
         {
             throw new ArgumentException(Environment.GetResourceString("Argument_ConstantDoesntMatch"));
         }
         writer.Write((byte) 0x54);
         this.EmitType(writer, propertyType);
         this.EmitString(writer, namedProperties[num].Name);
         this.EmitValue(writer, propertyType, propertyValues[num]);
     }
     for (num = 0; num < namedFields.Length; num++)
     {
         if (namedFields[num] == null)
         {
             throw new ArgumentNullException("namedFields[" + num + "]");
         }
         Type fieldType = namedFields[num].FieldType;
         if ((fieldValues[num] == null) && fieldType.IsPrimitive)
         {
             throw new ArgumentNullException("fieldValues[" + num + "]");
         }
         if (!this.ValidateType(fieldType))
         {
             throw new ArgumentException(Environment.GetResourceString("Argument_BadTypeInCustomAttribute"));
         }
         if ((((namedFields[num].DeclaringType != con.DeclaringType) && !(con.DeclaringType is TypeBuilderInstantiation)) && (!con.DeclaringType.IsSubclassOf(namedFields[num].DeclaringType) && !TypeBuilder.IsTypeEqual(namedFields[num].DeclaringType, con.DeclaringType))) && (!(namedFields[num].DeclaringType is TypeBuilder) || !con.DeclaringType.IsSubclassOf(((TypeBuilder) namedFields[num].DeclaringType).m_runtimeType)))
         {
             throw new ArgumentException(Environment.GetResourceString("Argument_BadFieldForConstructorBuilder"));
         }
         if (((fieldValues[num] != null) && (fieldType != typeof(object))) && (Type.GetTypeCode(fieldValues[num].GetType()) != Type.GetTypeCode(fieldType)))
         {
             throw new ArgumentException(Environment.GetResourceString("Argument_ConstantDoesntMatch"));
         }
         writer.Write((byte) 0x53);
         this.EmitType(writer, fieldType);
         this.EmitString(writer, namedFields[num].Name);
         this.EmitValue(writer, fieldType, fieldValues[num]);
     }
     this.m_blob = ((MemoryStream) writer.BaseStream).ToArray();
 }
 /// <summary>
 /// 创建构造方法参数表达式树集合
 /// </summary>
 /// <param name="constructor"></param>
 /// <returns></returns>
 private IEnumerable<Expression> GetConstructorParameters(ConstructorInfo constructor, IDependencyResolver resolver)
 {
     var lambdaParam = Expression.Parameter(typeof(object[]), "args");
     return constructor.GetParameterTypes().Select(parameterType => 
          Expression.Constant(resolver.Resolve(parameterType), parameterType));
 }
        public virtual void Emit(OpCode opcode, ConstructorInfo con) {
            int stackchange = 0;

            int tk = GetMethodToken(con, null);

            EnsureCapacity(7);
            InternalEmit(opcode);

            // Make a conservative estimate by assuming a return type and no
            // this parameter.
            if (opcode.m_push == StackBehaviour.Varpush)
            {
                // Instruction must be one of call or callvirt.
                BCLDebug.Assert(opcode.Equals(OpCodes.Call) ||
                                opcode.Equals(OpCodes.Callvirt),
                                "Unexpected opcode encountered for StackBehaviour of VarPush.");
                stackchange++;
            }
            if (opcode.m_pop == StackBehaviour.Varpop)
            {
                // Instruction must be one of call, callvirt or newobj.
                BCLDebug.Assert(opcode.Equals(OpCodes.Call) ||
                                opcode.Equals(OpCodes.Callvirt) ||
                                opcode.Equals(OpCodes.Newobj),
                                "Unexpected opcode encountered for StackBehaviour of VarPop.");

                if (con.GetParameterTypes() != null)
                    stackchange -= con.GetParameterTypes().Length;
            }
            UpdateStackSize(opcode, stackchange);

            RecordTokenFixup();
            m_length=PutInteger4(tk, m_length, m_ILStream);
        }