/// <summary>
		/// Write a value
		/// </summary>
		/// <param name="argType">The ctor arg type, field type, or property type</param>
		/// <param name="value">The value to write</param>
		void WriteElem(TypeSig argType, CAArgument value) {
			if (argType == null) {
				helper.Error("Arg type is null");
				argType = value.Type;
				if (argType == null)
					return;
			}
			if (!recursionCounter.Increment()) {
				helper.Error("Infinite recursion");
				return;
			}

			TypeSig underlyingType;
			ITypeDefOrRef tdr;
			switch (argType.ElementType) {
			case ElementType.Boolean:
				if (!VerifyTypeAndValue(value, ElementType.Boolean))
					writer.Write(ToUInt64(value.Value) != 0);
				else
					writer.Write((bool)value.Value);
				break;

			case ElementType.Char:
				if (!VerifyTypeAndValue(value, ElementType.Char))
					writer.Write((ushort)ToUInt64(value.Value));
				else
					writer.Write((ushort)(char)value.Value);
				break;

			case ElementType.I1:
				if (!VerifyTypeAndValue(value, ElementType.I1))
					writer.Write((sbyte)ToUInt64(value.Value));
				else
					writer.Write((sbyte)value.Value);
				break;

			case ElementType.U1:
				if (!VerifyTypeAndValue(value, ElementType.U1))
					writer.Write((byte)ToUInt64(value.Value));
				else
					writer.Write((byte)value.Value);
				break;

			case ElementType.I2:
				if (!VerifyTypeAndValue(value, ElementType.I2))
					writer.Write((short)ToUInt64(value.Value));
				else
					writer.Write((short)value.Value);
				break;

			case ElementType.U2:
				if (!VerifyTypeAndValue(value, ElementType.U2))
					writer.Write((ushort)ToUInt64(value.Value));
				else
					writer.Write((ushort)value.Value);
				break;

			case ElementType.I4:
				if (!VerifyTypeAndValue(value, ElementType.I4))
					writer.Write((int)ToUInt64(value.Value));
				else
					writer.Write((int)value.Value);
				break;

			case ElementType.U4:
				if (!VerifyTypeAndValue(value, ElementType.U4))
					writer.Write((uint)ToUInt64(value.Value));
				else
					writer.Write((uint)value.Value);
				break;

			case ElementType.I8:
				if (!VerifyTypeAndValue(value, ElementType.I8))
					writer.Write((long)ToUInt64(value.Value));
				else
					writer.Write((long)value.Value);
				break;

			case ElementType.U8:
				if (!VerifyTypeAndValue(value, ElementType.U8))
					writer.Write(ToUInt64(value.Value));
				else
					writer.Write((ulong)value.Value);
				break;

			case ElementType.R4:
				if (!VerifyTypeAndValue(value, ElementType.R4))
					writer.Write((float)ToDouble(value.Value));
				else
					writer.Write((float)value.Value);
				break;

			case ElementType.R8:
				if (!VerifyTypeAndValue(value, ElementType.R8))
					writer.Write(ToDouble(value.Value));
				else
					writer.Write((double)value.Value);
				break;

			case ElementType.String:
				if (VerifyTypeAndValue(value, ElementType.String, typeof(UTF8String)))
					WriteUTF8String((UTF8String)value.Value);
				else if (VerifyTypeAndValue(value, ElementType.String, typeof(string)))
					WriteUTF8String((string)value.Value);
				else
					WriteUTF8String(UTF8String.Empty);
				break;

			case ElementType.ValueType:
				tdr = ((TypeDefOrRefSig)argType).TypeDefOrRef;
				underlyingType = GetEnumUnderlyingType(argType);
				if (underlyingType != null)
					WriteElem(underlyingType, value);
				else if (tdr is TypeRef && TryWriteEnumUnderlyingTypeValue(value.Value)) {
					// No error. Assume it's an enum that couldn't be resolved.
				}
				else
					helper.Error("Custom attribute value is not an enum");
				break;

			case ElementType.Class:
				tdr = ((TypeDefOrRefSig)argType).TypeDefOrRef;
				if (CheckCorLibType(argType, "Type")) {
					if (CheckCorLibType(value.Type, "Type")) {
						var ts = value.Value as TypeSig;
						if (ts != null)
							WriteType(ts);
						else {
							helper.Error("CA value is not a type");
							WriteUTF8String(UTF8String.Empty);
						}
					}
					else {
						helper.Error("CA value type is not System.Type");
						WriteUTF8String(UTF8String.Empty);
					}
					break;
				}
				else if (tdr is TypeRef && TryWriteEnumUnderlyingTypeValue(value.Value)) {
					// No error. Assume it's an enum that couldn't be resolved.
					break;
				}
				goto default;

			case ElementType.SZArray:
				WriteValue(argType, value);
				break;

			case ElementType.Object:
				WriteFieldOrPropType(value.Type);
				WriteElem(value.Type, value);
				break;

			case ElementType.End:
			case ElementType.Void:
			case ElementType.Ptr:
			case ElementType.ByRef:
			case ElementType.Var:
			case ElementType.Array:
			case ElementType.GenericInst:
			case ElementType.TypedByRef:
			case ElementType.ValueArray:
			case ElementType.I:
			case ElementType.U:
			case ElementType.R:
			case ElementType.FnPtr:
			case ElementType.MVar:
			case ElementType.CModReqd:
			case ElementType.CModOpt:
			case ElementType.Internal:
			case ElementType.Module:
			case ElementType.Sentinel:
			case ElementType.Pinned:
			default:
				helper.Error("Invalid or unsupported element type in custom attribute");
				break;
			}

			recursionCounter.Decrement();
		}
		bool VerifyTypeAndValue(CAArgument value, ElementType etype, Type valueType) {
			if (!VerifyType(value.Type, etype)) {
				helper.Error("Custom attribute arg type != value.Type");
				return false;
			}
			return value.Value == null || value.Value.GetType() == valueType;
		}
		bool VerifyTypeAndValue(CAArgument value, ElementType etype) {
			if (!VerifyType(value.Type, etype)) {
				helper.Error("Custom attribute arg type != value.Type");
				return false;
			}
			if (!VerifyValue(value.Value, etype)) {
				helper.Error("Custom attribute value.Value's type != value.Type");
				return false;
			}
			return true;
		}
		void WriteValue(TypeSig argType, CAArgument value) {
			if (argType == null || value.Type == null) {
				helper.Error("Argument type is null");
				return;
			}
			if (!recursionCounter.Increment()) {
				helper.Error("Infinite recursion");
				return;
			}

			var arrayType = argType as SZArraySig;
			if (arrayType != null) {
				var argsArray = value.Value as IList<CAArgument>;
				if (argsArray == null && value.Value != null)
					helper.Error("Value is not null or an array");
				WriteArrayValue(arrayType, argsArray);
			}
			else
				WriteElem(argType, value);

			recursionCounter.Decrement();
		}
Пример #5
0
 void Add(CAArgument arg)
 {
     // It's a struct so can't be null
     Add(arg.Type);
 }
Пример #6
0
 public ConstructorArgumentWrapper(CAArgument ca)
 {
     Value = ca.Value;
 }