| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- //
- // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- //
- // System.Reflection.Emit/CustomAttributeBuilder.cs
- //
- // Author:
- // Paolo Molaro ([email protected])
- //
- // (C) 2001 Ximian, Inc. http://www.ximian.com
- //
- using System;
- using System.Reflection;
- using System.Reflection.Emit;
- using System.Runtime.CompilerServices;
- using System.Runtime.InteropServices;
- namespace System.Reflection.Emit {
- public class CustomAttributeBuilder {
- ConstructorInfo ctor;
- byte[] data;
- internal ConstructorInfo Ctor {
- get {return ctor;}
- }
- internal byte[] Data {
- get {return data;}
- }
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- static extern byte[] GetBlob(Assembly asmb, ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues, FieldInfo[] namedFields, object[] fieldValues);
-
- internal CustomAttributeBuilder( ConstructorInfo con, byte[] cdata) {
- ctor = con;
- data = (byte[])cdata.Clone ();
- /* should we check that the user supplied data is correct? */
- }
-
- public CustomAttributeBuilder( ConstructorInfo con, object[] constructorArgs)
- {
- Initialize (con, constructorArgs, new PropertyInfo [0], new object [0],
- new FieldInfo [0], new object [0]);
- }
- public CustomAttributeBuilder( ConstructorInfo con, object[] constructorArgs,
- FieldInfo[] namedFields, object[] fieldValues)
- {
- Initialize (con, constructorArgs, new PropertyInfo [0], new object [0],
- namedFields, fieldValues);
- }
- public CustomAttributeBuilder( ConstructorInfo con, object[] constructorArgs,
- PropertyInfo[] namedProperties, object[] propertyValues)
- {
- Initialize (con, constructorArgs, namedProperties, propertyValues, new FieldInfo [0],
- new object [0]);
- }
- public CustomAttributeBuilder( ConstructorInfo con, object[] constructorArgs,
- PropertyInfo[] namedProperties, object[] propertyValues,
- FieldInfo[] namedFields, object[] fieldValues)
- {
- Initialize (con, constructorArgs, namedProperties, propertyValues, namedFields, fieldValues);
- }
- private void Initialize (ConstructorInfo con, object [] constructorArgs,
- PropertyInfo [] namedProperties, object [] propertyValues,
- FieldInfo [] namedFields, object [] fieldValues)
- {
- ctor = con;
- if (con == null)
- throw new ArgumentNullException ("con");
- if (constructorArgs == null)
- throw new ArgumentNullException ("constructorArgs");
- if (namedProperties == null)
- throw new ArgumentNullException ("namedProperties");
- if (propertyValues == null)
- throw new ArgumentNullException ("propertyValues");
- if (namedFields == null)
- throw new ArgumentNullException ("namedFields");
- if (fieldValues == null)
- throw new ArgumentNullException ("fieldValues");
- if (con.GetParameterCount () != constructorArgs.Length)
- throw new ArgumentException ("Parameter count does not match " +
- "passed in argument value count.");
- if (namedProperties.Length != propertyValues.Length)
- throw new ArgumentException ("Array lengths must be the same.",
- "namedProperties, propertyValues");
- if (namedFields.Length != fieldValues.Length)
- throw new ArgumentException ("Array lengths must be the same.",
- "namedFields, fieldValues");
- if ((con.Attributes & MethodAttributes.Static) == MethodAttributes.Static ||
- (con.Attributes & MethodAttributes.Private) == MethodAttributes.Private)
- throw new ArgumentException ("Cannot have private or static constructor.");
- Type atype = ctor.DeclaringType;
- int i;
- i = 0;
- foreach (FieldInfo fi in namedFields) {
- Type t = fi.DeclaringType;
- if ((atype != t) && (!t.IsSubclassOf (atype)) && (!atype.IsSubclassOf (t)))
- throw new ArgumentException ("Field '" + fi.Name + "' does not belong to the same class as the constructor");
- // 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 ())) {
- //
- // mcs allways uses object[] for array types and
- // MS.NET allows this
- //
- if (!fi.FieldType.IsArray)
- throw new ArgumentException ("Value of field '" + fi.Name + "' does not match field type: " + fi.FieldType);
- }
- i ++;
- }
- i = 0;
- foreach (PropertyInfo pi in namedProperties) {
- if (!pi.CanWrite)
- throw new ArgumentException ("Property '" + pi.Name + "' does not have a setter.");
- Type t = pi.DeclaringType;
- 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.IsArray)
- throw new ArgumentException ("Value of property '" + pi.Name + "' does not match property type: " + pi.PropertyType + " -> " + propertyValues [i]);
- }
- i ++;
- }
- i = 0;
- foreach (ParameterInfo pi in con.GetParameters ()) {
- if (pi != null) {
- Type paramType = pi.ParameterType;
- if (constructorArgs [i] != null)
- if (!(paramType is TypeBuilder) && !paramType.IsEnum && !paramType.IsAssignableFrom (constructorArgs [i].GetType ()))
- if (!paramType.IsArray)
- throw new ArgumentException ("Value of argument " + i + " does not match parameter type: " + paramType + " -> " + constructorArgs [i]);
- }
- i ++;
- }
-
- data = GetBlob (atype.Assembly, con, constructorArgs, namedProperties, propertyValues, namedFields, fieldValues);
- }
- /* helper methods */
- internal static int decode_len (byte[] data, int pos, out int rpos) {
- int len = 0;
- if ((data [pos] & 0x80) == 0) {
- len = (int)(data [pos++] & 0x7f);
- } else if ((data [pos] & 0x40) == 0) {
- len = ((data [pos] & 0x3f) << 8) + data [pos + 1];
- pos += 2;
- } else {
- len = ((data [pos] & 0x1f) << 24) + (data [pos + 1] << 16) + (data [pos + 2] << 8) + data [pos + 3];
- pos += 4;
- }
- rpos = pos;
- return len;
- }
- internal static string string_from_bytes (byte[] data, int pos, int len)
- {
- return System.Text.Encoding.UTF8.GetString(data, pos, len);
- }
- internal string string_arg ()
- {
- int pos = 2;
- int len = decode_len (data, pos, out pos);
- return string_from_bytes (data, pos, len);
- }
- internal static UnmanagedMarshal get_umarshal (CustomAttributeBuilder customBuilder, bool is_field) {
- byte[] data = customBuilder.Data;
- UnmanagedType subtype = UnmanagedType.I4;
- int sizeConst = 0;
- int value;
- int utype; /* the (stupid) ctor takes a short or an enum ... */
- utype = (int)data [2];
- utype |= ((int)data [3]) << 8;
- string first_type_name = customBuilder.Ctor.GetParameters()[0].ParameterType.FullName;
- int pos = 6;
- if (first_type_name == "System.Int16")
- pos = 4;
- int nnamed = (int)data [pos++];
- nnamed |= ((int)data [pos++]) << 8;
-
- for (int i = 0; i < nnamed; ++i) {
- int paramType; // What is this ?
- paramType = (int)data [pos++];
- paramType |= ((int)data [pos++]) << 8;
- int len = decode_len (data, pos, out pos);
- string named_name = string_from_bytes (data, pos, len);
- pos += len;
- switch (named_name) {
- case "ArraySubType":
- value = (int)data [pos++];
- value |= ((int)data [pos++]) << 8;
- value |= ((int)data [pos++]) << 16;
- value |= ((int)data [pos++]) << 24;
- subtype = (UnmanagedType)value;
- break;
- case "SizeConst":
- value = (int)data [pos++];
- value |= ((int)data [pos++]) << 8;
- value |= ((int)data [pos++]) << 16;
- value |= ((int)data [pos++]) << 24;
- sizeConst = value;
- break;
- default:
- break;
- }
- }
- switch ((UnmanagedType)utype) {
- case UnmanagedType.LPArray:
- return UnmanagedMarshal.DefineLPArray (subtype);
- case UnmanagedType.SafeArray:
- return UnmanagedMarshal.DefineSafeArray (subtype);
- case UnmanagedType.ByValArray:
- return UnmanagedMarshal.DefineByValArray (sizeConst);
- case UnmanagedType.ByValTStr:
- return UnmanagedMarshal.DefineByValTStr (sizeConst);
- default:
- return UnmanagedMarshal.DefineUnmanagedMarshal ((UnmanagedType)utype);
- }
- }
- }
- }
|