using System.Runtime.InteropServices;
namespace System.Reflection.Emit {
+#if NET_2_0
+ [ComVisible (true)]
+ [ClassInterfaceAttribute (ClassInterfaceType.None)]
+ [ComDefaultInterfaceAttribute (typeof (_CustomAttributeBuilder))]
+#endif
public class CustomAttributeBuilder {
ConstructorInfo ctor;
byte[] data;
// FIXME: Check enums and TypeBuilders as well
if (fieldValues [i] != null)
// IsEnum does not seem to work on TypeBuilders
- if (!(fi.FieldType is TypeBuilder) && !fi.FieldType.IsEnum && !fi.FieldType.IsAssignableFrom (fieldValues [i].GetType ())) {
+ if (!(fi.FieldType is TypeBuilder) && !fi.FieldType.IsEnum && !fi.FieldType.IsInstanceOfType (fieldValues [i])) {
//
// mcs allways uses object[] for array types and
// MS.NET allows this
if ((atype != t) && (!t.IsSubclassOf (atype)) && (!atype.IsSubclassOf (t)))
throw new ArgumentException ("Property '" + pi.Name + "' does not belong to the same class as the constructor");
if (propertyValues [i] != null) {
- if (!(pi.PropertyType is TypeBuilder) && !pi.PropertyType.IsEnum && !pi.PropertyType.IsAssignableFrom (propertyValues [i].GetType ()))
+ if (!(pi.PropertyType is TypeBuilder) && !pi.PropertyType.IsEnum && !pi.PropertyType.IsInstanceOfType (propertyValues [i]))
if (!pi.PropertyType.IsArray)
throw new ArgumentException ("Value of property '" + pi.Name + "' does not match property type: " + pi.PropertyType + " -> " + propertyValues [i]);
}
if (!IsValidType (paramType))
throw new ArgumentException ("Argument " + i + " does not have a valid type.");
if (constructorArgs [i] != null)
- if (!(paramType is TypeBuilder) && !paramType.IsEnum && !paramType.IsAssignableFrom (constructorArgs [i].GetType ()))
+ if (!(paramType is TypeBuilder) && !paramType.IsEnum && !paramType.IsInstanceOfType (constructorArgs [i]))
if (!paramType.IsArray)
throw new ArgumentException ("Value of argument " + i + " does not match parameter type: " + paramType + " -> " + constructorArgs [i]);
}
}
}
+ static object decode_cattr_value (Type t, byte[] data, int pos, out int rpos) {
+ switch (Type.GetTypeCode (t)) {
+ case TypeCode.String:
+ int len = decode_len (data, pos, out pos);
+ rpos = pos + len;
+ return string_from_bytes (data, pos, len);
+ case TypeCode.Int32:
+ rpos = pos + 4;
+ return data [pos] + (data [pos + 1] << 8) + (data [pos + 2] << 16) + (data [pos + 3] << 24);
+ case TypeCode.Boolean:
+ rpos = pos + 1;
+ return (data [pos] == 0) ? false : true;
+ default:
+ throw new Exception ("FIXME: Type " + t + " not yet handled in decode_cattr_value.");
+ }
+ }
+
+ internal struct CustomAttributeInfo {
+ public ConstructorInfo ctor;
+ public object[] ctorArgs;
+ public string[] namedParamNames;
+ public object[] namedParamValues;
+ }
+
+ internal static CustomAttributeInfo decode_cattr (CustomAttributeBuilder customBuilder) {
+ byte[] data = customBuilder.Data;
+ ConstructorInfo ctor = customBuilder.Ctor;
+ int pos = 0;
+
+ CustomAttributeInfo info = new CustomAttributeInfo ();
+
+ // Prolog
+ if (data.Length < 2)
+ throw new Exception ();
+ if ((data [0] != 0x1) || (data [1] != 0x00))
+ throw new Exception ();
+ pos = 2;
+
+ ParameterInfo [] pi = ctor.GetParameters ();
+ info.ctor = ctor;
+ info.ctorArgs = new object [pi.Length];
+ for (int i = 0; i < pi.Length; ++i)
+ info.ctorArgs [i] = decode_cattr_value (pi [i].ParameterType, data, pos, out pos);
+
+ int num_named = data [pos] + (data [pos + 1] * 256);
+ pos += 2;
+
+ info.namedParamNames = new string [num_named];
+ info.namedParamValues = new object [num_named];
+ for (int i = 0; i < num_named; ++i) {
+ int named_type = data [pos++];
+ int data_type = data [pos++];
+ string enum_type_name = null;
+
+ if (data_type == 0x55) {
+ int len2 = decode_len (data, pos, out pos);
+ enum_type_name = string_from_bytes (data, pos, len2);
+ pos += len2;
+ }
+
+ int len = decode_len (data, pos, out pos);
+ string name = string_from_bytes (data, pos, len);
+ info.namedParamNames [i] = name;
+ pos += len;
+
+ if (named_type == 0x53) {
+ /* Field */
+ FieldInfo fi = ctor.DeclaringType.GetField (name, BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance);
+ if (fi == null)
+ throw new Exception ("Custom attribute type '" + ctor.DeclaringType + "' doesn't contain a field named '" + name + "'");
+
+ object val = decode_cattr_value (fi.FieldType, data, pos, out pos);
+ if (enum_type_name != null) {
+ Type enumType = Type.GetType (enum_type_name);
+ val = Enum.ToObject (enumType, val);
+ }
+
+ info.namedParamValues [i] = val;
+ }
+ else
+ // FIXME:
+ throw new Exception ();
+ }
+
+ return info;
+ }
}
}