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]);
}
internal static UnmanagedMarshal get_umarshal (CustomAttributeBuilder customBuilder, bool is_field) {
byte[] data = customBuilder.Data;
- UnmanagedType subtype = UnmanagedType.I4;
- int sizeConst = 0;
+ UnmanagedType subtype = (UnmanagedType)0x50; /* NATIVE_MAX */
+ int sizeConst = -1;
+ int sizeParamIndex = -1;
+ bool hasSize = false;
int value;
int utype; /* the (stupid) ctor takes a short or an enum ... */
Type marshalTypeRef = null;
value |= ((int)data [pos++]) << 16;
value |= ((int)data [pos++]) << 24;
sizeConst = value;
+ hasSize = true;
+ break;
+ case "SizeSizeParamIndex":
+ value = (int)data [pos++];
+ value |= ((int)data [pos++]) << 8;
+ sizeParamIndex = value;
+ hasSize = true;
break;
case "MarshalTypeRef":
case "MarshalType":
break;
default:
len = decode_len(data, pos, out pos);
- string v = string_from_bytes (data, pos, len);
+ string_from_bytes (data, pos, len);
pos += len;
break;
}
switch ((UnmanagedType)utype) {
case UnmanagedType.LPArray:
- return UnmanagedMarshal.DefineLPArray (subtype);
+ if (hasSize)
+ return UnmanagedMarshal.DefineLPArrayInternal (subtype, sizeConst, sizeParamIndex);
+ else
+ return UnmanagedMarshal.DefineLPArray (subtype);
case UnmanagedType.SafeArray:
return UnmanagedMarshal.DefineSafeArray (subtype);
case UnmanagedType.ByValArray:
}
}
+ 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;
+ }
}
}