/// <summary>
 /// Writes the named argument to the provided output stream.
 /// </summary>
 /// <param name="writer">The output stream.</param>
 /// <param name="provider">The object to use for obtaining metadata tokens for members in the tables stream.</param>
 public void Write(IBinaryStreamWriter writer, ITypeCodedIndexProvider provider)
 {
     writer.WriteByte((byte)MemberType);
     TypeSignature.WriteFieldOrPropType(writer, ArgumentType);
     writer.WriteSerString(MemberName);
     Argument.Write(writer, provider);
 }
        /// <summary>
        /// Writes the named argument to the provided output stream.
        /// </summary>
        public void Write(BlobSerializationContext context)
        {
            var writer = context.Writer;

            writer.WriteByte((byte)MemberType);
            TypeSignature.WriteFieldOrPropType(writer, ArgumentType);
            writer.WriteSerString(MemberName);
            Argument.Write(context);
        }
Example #3
0
        private void WriteValue(IBinaryStreamWriter writer, TypeSignature argumentType, ITypeCodedIndexProvider provider, object value)
        {
            if (argumentType.IsTypeOf("System", "Type"))
            {
                writer.WriteSerString(TypeNameBuilder.GetAssemblyQualifiedName((TypeSignature)value));
                return;
            }

            switch (argumentType.ElementType)
            {
            case ElementType.Boolean:
                writer.WriteByte((byte)((bool)value ? 1 : 0));
                break;

            case ElementType.Char:
                writer.WriteUInt16((char)value);
                break;

            case ElementType.I1:
                writer.WriteSByte((sbyte)value);
                break;

            case ElementType.U1:
                writer.WriteByte((byte)value);
                break;

            case ElementType.I2:
                writer.WriteInt16((short)value);
                break;

            case ElementType.U2:
                writer.WriteUInt16((ushort)value);
                break;

            case ElementType.I4:
                writer.WriteInt32((int)value);
                break;

            case ElementType.U4:
                writer.WriteUInt32((uint)value);
                break;

            case ElementType.I8:
                writer.WriteInt64((long)value);
                break;

            case ElementType.U8:
                writer.WriteUInt64((ulong)value);
                break;

            case ElementType.R4:
                writer.WriteSingle((float)value);
                break;

            case ElementType.R8:
                writer.WriteDouble((double)value);
                break;

            case ElementType.String:
                writer.WriteSerString(value as string);
                break;

            case ElementType.Object:
                var valueType    = value.GetType();
                var innerTypeSig = argumentType.Module.CorLibTypeFactory.FromName(valueType.Namespace, valueType.Name);
                TypeSignature.WriteFieldOrPropType(writer, innerTypeSig);
                WriteValue(writer, innerTypeSig, provider, value);
                break;

            case ElementType.Class:
            case ElementType.Enum:
            case ElementType.ValueType:
                var enumTypeDef = argumentType.Resolve();
                if (enumTypeDef != null && enumTypeDef.IsEnum)
                {
                    WriteValue(writer, enumTypeDef.GetEnumUnderlyingType(), provider, Value);
                }
                else
                {
                    throw new NotImplementedException();
                }
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
        private void WriteElement(TypeSignature argumentType, object element)
        {
            var writer = _context.Writer;

            if (argumentType.IsTypeOf("System", "Type"))
            {
                writer.WriteSerString(TypeNameBuilder.GetAssemblyQualifiedName((TypeSignature)element));
                return;
            }

            switch (argumentType.ElementType)
            {
            case ElementType.Boolean:
                writer.WriteByte((byte)((bool)element ? 1 : 0));
                break;

            case ElementType.Char:
                writer.WriteUInt16((char)element);
                break;

            case ElementType.I1:
                writer.WriteSByte((sbyte)element);
                break;

            case ElementType.U1:
                writer.WriteByte((byte)element);
                break;

            case ElementType.I2:
                writer.WriteInt16((short)element);
                break;

            case ElementType.U2:
                writer.WriteUInt16((ushort)element);
                break;

            case ElementType.I4:
                writer.WriteInt32((int)element);
                break;

            case ElementType.U4:
                writer.WriteUInt32((uint)element);
                break;

            case ElementType.I8:
                writer.WriteInt64((long)element);
                break;

            case ElementType.U8:
                writer.WriteUInt64((ulong)element);
                break;

            case ElementType.R4:
                writer.WriteSingle((float)element);
                break;

            case ElementType.R8:
                writer.WriteDouble((double)element);
                break;

            case ElementType.String:
                writer.WriteSerString(element as string);
                break;

            case ElementType.Object:
                TypeSignature innerTypeSig;
                object        value;

                if (element is null)
                {
                    // Most efficient way to store "null" is writing null as a string (two bytes).
                    innerTypeSig = argumentType.Module.CorLibTypeFactory.String;
                    value        = null;
                }
                else if (element is BoxedArgument boxedArgument)
                {
                    // Write the boxed argument.
                    innerTypeSig = boxedArgument.Type;
                    value        = boxedArgument.Value;
                }
                else
                {
                    _context.DiagnosticBag.RegisterException(new NotSupportedException(
                                                                 $"Object elements in a custom attribute signature should be either 'null' or an instance of {nameof(BoxedArgument)}."));

                    // Write null as a recovery.
                    innerTypeSig = argumentType.Module.CorLibTypeFactory.String;
                    value        = null;
                }

                TypeSignature.WriteFieldOrPropType(writer, innerTypeSig);
                WriteElement(innerTypeSig, value);
                break;

            case ElementType.SzArray:
                WriteArrayElement(
                    (SzArrayTypeSignature)argumentType,
                    element as IList <object> ?? new object[0],
                    element == null);
                break;

            case ElementType.Class:
            case ElementType.Enum:
            case ElementType.ValueType:
                WriteEnumValue(argumentType, element);
                break;

            default:
                UnsupportedArgumentType(argumentType);
                break;
            }
        }