/// <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)); }
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); }