internal void InitCustomAttributeBuilder(ConstructorInfo con, Object[] constructorArgs, PropertyInfo[] namedProperties, Object[] propertyValues, FieldInfo[] namedFields, Object[] fieldValues) { if (con == null) throw new ArgumentNullException("con"); if (constructorArgs == null) throw new ArgumentNullException("constructorArgs"); if (namedProperties == null) throw new ArgumentNullException("constructorArgs"); 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")); // Cache information used elsewhere. m_con = con; m_constructorArgs = new Object[constructorArgs.Length]; Array.Copy(constructorArgs, m_constructorArgs, constructorArgs.Length); Type[] paramTypes; int i; // Get the types of the constructor's formal parameters. if (con is ConstructorBuilder) { paramTypes = ((ConstructorBuilder)con).GetParameterTypes(); } else { ParameterInfo[] paramInfos = con.GetParametersNoCopy(); paramTypes = new Type[paramInfos.Length]; for (i = 0; i < paramInfos.Length; i++) paramTypes[i] = paramInfos[i].ParameterType; } // 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++) { if (constructorArgs[i] == null) continue; TypeCode paramTC = Type.GetTypeCode(paramTypes[i]); if (paramTC != Type.GetTypeCode(constructorArgs[i].GetType())) if (paramTC != TypeCode.Object || !ValidateType(constructorArgs[i].GetType())) throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_BadParameterTypeForConstructor"), 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. if (namedProperties[i] == null) throw new ArgumentNullException("namedProperties[" + i + "]"); // Allow null for non-primitive types only. Type propType = namedProperties[i].PropertyType; if (propertyValues[i] == null && propType.IsPrimitive) throw new ArgumentNullException("propertyValues[" + i + "]"); // Validate property type. if (!ValidateType(propType)) throw new ArgumentException(Environment.GetResourceString("Argument_BadTypeInCustomAttribute")); // Property has to be writable. if (!namedProperties[i].CanWrite) throw new ArgumentException(Environment.GetResourceString("Argument_NotAWritableProperty")); // Property has to be from the same class or base class as ConstructorInfo. if (namedProperties[i].DeclaringType != con.DeclaringType && (!(con.DeclaringType is TypeBuilderInstantiation)) && !con.DeclaringType.IsSubclassOf(namedProperties[i].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(namedProperties[i].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 (!(namedProperties[i].DeclaringType is TypeBuilder) || !con.DeclaringType.IsSubclassOf(((TypeBuilder)namedProperties[i].DeclaringType).m_runtimeType)) 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 (propertyValues[i] != null && propType != typeof(Object) && Type.GetTypeCode(propertyValues[i].GetType()) != Type.GetTypeCode(propType)) throw new ArgumentException(Environment.GetResourceString("Argument_ConstantDoesntMatch")); // First a byte indicating that this is a property. writer.Write(SERIALIZATION_TYPE_PROPERTY); // Emit the property type, name and value. EmitType(writer, propType); EmitString(writer, namedProperties[i].Name); EmitValue(writer, propType, propertyValues[i]); } // Emit all the field sets. for (i = 0; i < namedFields.Length; i++) { // Validate the field. if (namedFields[i] == null) throw new ArgumentNullException("namedFields[" + i + "]"); // Allow null for non-primitive types only. Type fldType = namedFields[i].FieldType; if (fieldValues[i] == null && fldType.IsPrimitive) 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 (namedFields[i].DeclaringType != con.DeclaringType && (!(con.DeclaringType is TypeBuilderInstantiation)) && !con.DeclaringType.IsSubclassOf(namedFields[i].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(namedFields[i].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 (!(namedFields[i].DeclaringType is TypeBuilder) || !con.DeclaringType.IsSubclassOf(((TypeBuilder)namedFields[i].DeclaringType).m_runtimeType)) 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 (fieldValues[i] != null && fldType != typeof(Object) && Type.GetTypeCode(fieldValues[i].GetType()) != Type.GetTypeCode(fldType)) throw new ArgumentException(Environment.GetResourceString("Argument_ConstantDoesntMatch")); // First a byte indicating that this is a field. writer.Write(SERIALIZATION_TYPE_FIELD); // Emit the field type, name and value. EmitType(writer, fldType); EmitString(writer, namedFields[i].Name); EmitValue(writer, fldType, fieldValues[i]); } // Create the blob array. m_blob = ((MemoryStream)writer.BaseStream).ToArray(); }
[System.Security.SecuritySafeCritical] // auto-generated private CustomAttributeData(RuntimeModule scope, CustomAttributeRecord caRecord) { m_scope = scope; m_ctor = (RuntimeConstructorInfo)RuntimeType.GetMethodBase(scope, caRecord.tkCtor); ParameterInfo[] parameters = m_ctor.GetParametersNoCopy(); m_ctorParams = new CustomAttributeCtorParameter[parameters.Length]; for (int i = 0; i < parameters.Length; i++) m_ctorParams[i] = new CustomAttributeCtorParameter(InitCustomAttributeType((RuntimeType)parameters[i].ParameterType)); FieldInfo[] fields = m_ctor.DeclaringType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); PropertyInfo[] properties = m_ctor.DeclaringType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); m_namedParams = new CustomAttributeNamedParameter[properties.Length + fields.Length]; for (int i = 0; i < fields.Length; i++) m_namedParams[i] = new CustomAttributeNamedParameter( fields[i].Name, CustomAttributeEncoding.Field, InitCustomAttributeType((RuntimeType)fields[i].FieldType)); for (int i = 0; i < properties.Length; i++) m_namedParams[i + fields.Length] = new CustomAttributeNamedParameter( properties[i].Name, CustomAttributeEncoding.Property, InitCustomAttributeType((RuntimeType)properties[i].PropertyType)); m_members = new MemberInfo[fields.Length + properties.Length]; fields.CopyTo(m_members, 0); properties.CopyTo(m_members, fields.Length); CustomAttributeEncodedArgument.ParseAttributeArguments(caRecord.blob, ref m_ctorParams, ref m_namedParams, m_scope); }