/*
The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language
governing rights and limitations under the License.
The Original Code is RAIL(Runtime Assembly Instrumentation Library) Alpha Version.
The Initial Developer of the Original Code is University of Coimbra,
Computer Science Department, Dependable Systems Group. Copyright (C) University of Coimbra.
All Rights Reserved.
*/
using System;
using System.Reflection;
using System.Collections;
using Mono.PEToolkit;
using Mono.PEToolkit.Metadata;
using System.Text;
namespace Rail.Reflect{
/// <summary>
/// Represents a custom attribute.
/// </summary>
/// <remarks>
/// Elements of a C# program that support custom attributes:
/// assembly, module, type, field, method, method parameter,
/// method return value, property, and event.
///
/// The purpose of this class is to:
/// - Create new CustomAttributes instances
/// - Change existing instances (its fields, the arguments
/// for the constructor, the arguments of the properties)
///
/// Therefore, it must be possible to:
/// - Obtain RCustomAttrib objects from existing types
/// - Change its values.
///</remarks>
/// This class is not called RCustomAttrib because .Net conventions state
/// that classes ending in Attribute should be custom attributes.
public class RCustomAttrib
{
#region fields
/// <summary>
///
/// </summary>
protected RConstructor customAttributeCtor;
// /// <summary>
// ///
// /// </summary>
// protected Object ctorArgs;
/// <summary>
///
/// </summary>
protected byte [] customAttributeData;
/// <summary>
///
/// </summary>
protected ArrayList customAttributeProp;
/// <summary>
///
/// </summary>
protected ArrayList propertyValues;
/// <summary>
///
/// </summary>
protected ArrayList customAttributeFields;
/// <summary>
///
/// </summary>
protected ArrayList fieldsValues;
/// <summary>
///
/// </summary>
protected Object[] constructorArguments;
private RAssemblyDef rAssemblyDef;
#endregion
/// <summary>
/// Initializes a new instance of the custom attribute. To build this object
/// it is necessary to provide all the required information to instantiate
/// a new instance of the underlying custom attribute class. So, if this
/// object represents an instance of AssemblyCultureInformation it is
/// necessary to provide its constructor and the arguments to be used to
/// initialize it. Use the other overloaded version of this constructor
/// to initialize the properties and fields of the attribute instance.
/// </summary>
/// <param name="customAttributeCtor"></param>
/// <param name="ctorArgs"></param>
// public RCustomAttrib(RConstructor customAttributeCtor, Object ctorArgs)
// {
// this.customAttributeCtor = customAttributeCtor;
// this.ctorArgs = ctorArgs;
// }
/// <summary>
///
/// </summary>
/// <param name="customAttributeCtor"></param>
/// <param name="customAttributeData"></param>
public RCustomAttrib(RConstructor customAttributeCtor, byte [] customAttributeData, RAssemblyDef rAssemblyDef)
{
this.customAttributeCtor = customAttributeCtor;
this.customAttributeData = customAttributeData;
this.rAssemblyDef = rAssemblyDef;
if (this.customAttributeCtor != null &&
this.customAttributeCtor.ParametersCount > 0 &&
this.customAttributeData != null &&
this.customAttributeData.Length > 0)
{
int offset = 0;
if (LEBitConverter.ToInt16(this.customAttributeData,offset) != 0x0001)
throw new InvalidProgramException("Invalid Prolog in Custom attribute value blob");
offset += 2;
this.constructorArguments = new Object[this.customAttributeCtor.ParametersCount];
for (int i = 1; i <= this.customAttributeCtor.ParametersCount; i++)
{
RParameter currParameter = this.customAttributeCtor.GetParameter(i) as RParameter;
if (currParameter.ParameterType.IsArray)
{
int arraySize = LEBitConverter.ToInt32(this.customAttributeData,offset);
offset += 4;
object [] objectArray = new object[arraySize];
for (int j=0; j<arraySize; j++)
{
objectArray[j] = GetElem(currParameter,this.customAttributeData,out offset,offset);
}
this.constructorArguments[i-1] = objectArray;
}
else
{
this.constructorArguments[i-1] = GetElem(currParameter,this.customAttributeData,out offset,offset);
}
}
this.customAttributeFields = new ArrayList();
this.customAttributeProp = new ArrayList();
this.fieldsValues = new ArrayList();
this.propertyValues = new ArrayList();
int NumNamed = LEBitConverter.ToInt16(this.customAttributeData,offset);
offset += 2;
int stringSize = 0;
byte [] data_array;
string name;
if (NumNamed>0)
{
for (int j=0; j<NumNamed; j++)
{
if (this.customAttributeData[offset]==0x53)
{
//Field
++offset;
RFieldDef field = new RFieldDef();
field.DeclaringType = this.AttributeConstructor.DeclaringType;
ElementType FieldOrPropType = (ElementType)this.customAttributeData[offset];
switch (FieldOrPropType)
{
case ElementType.Boolean:
field.FieldType = this.rAssemblyDef.GetRTypeRef(typeof(System.Boolean));
break;
case ElementType.Char:
field.FieldType = this.rAssemblyDef.GetRTypeRef(typeof(System.Char));
break;
case ElementType.I1:
field.FieldType = this.rAssemblyDef.GetRTypeRef(typeof(System.SByte));
break;
case ElementType.I2:
field.FieldType = this.rAssemblyDef.GetRTypeRef(typeof(System.Int16));
break;
case ElementType.I4:
field.FieldType = this.rAssemblyDef.GetRTypeRef(typeof(System.Int32));
break;
case ElementType.I8:
field.FieldType = this.rAssemblyDef.GetRTypeRef(typeof(System.Int64));
break;
case ElementType.U1:
field.FieldType = this.rAssemblyDef.GetRTypeRef(typeof(System.Byte));
break;
case ElementType.U2:
field.FieldType = this.rAssemblyDef.GetRTypeRef(typeof(System.UInt16));
break;
case ElementType.U4:
field.FieldType = this.rAssemblyDef.GetRTypeRef(typeof(System.UInt32));
break;
case ElementType.U8:
field.FieldType = this.rAssemblyDef.GetRTypeRef(typeof(System.UInt64));
break;
case ElementType.R4:
field.FieldType = this.rAssemblyDef.GetRTypeRef(typeof(System.Single));
break;
case ElementType.R8:
field.FieldType = this.rAssemblyDef.GetRTypeRef(typeof(System.Double));
break;
case ElementType.String:
field.FieldType = this.rAssemblyDef.GetRTypeRef(typeof(System.String));
break;
case ElementType.Type:
field.FieldType = this.rAssemblyDef.GetRTypeRef(typeof(System.Type));
break;
case ElementType.Enum:
++offset;
stringSize = MetadataSignatures.ReadCompressedInt(this.customAttributeData, out offset,offset);
data_array = new byte[stringSize];
for (int x=offset; x< stringSize+offset ; x++)
data_array[x-offset] = this.customAttributeData[x];
name = Encoding.UTF8.GetString(data_array);
field.FieldType = this.rAssemblyDef.GetRTypeRef(name);
if (field.FieldType==null)
field.FieldType = this.rAssemblyDef.RModuleDef.GetType(name);
offset += stringSize - 1;
break;
}
++offset;
stringSize = MetadataSignatures.ReadCompressedInt(this.customAttributeData, out offset,offset);
data_array = new byte[stringSize];
for (int x=offset; x< stringSize+offset ; x++)
data_array[x-offset] = this.customAttributeData[x];
name = Encoding.UTF8.GetString(data_array);
field.Name = name;
offset += stringSize;
if (field.FieldType.IsArray)
{
int arraySize = LEBitConverter.ToInt32(this.customAttributeData,offset);
offset += 4;
object [] objectArray = new object[arraySize];
for (int x=0; x<arraySize; x++)
{
objectArray[x] = GetElem(field.FieldType,this.customAttributeData,out offset,offset);
}
field.Value = objectArray;
}
else
{
field.Value = GetElem(field.FieldType,this.customAttributeData,out offset,offset);
}
this.fieldsValues.Add(field.Value);
this.customAttributeFields.Add(field);
}
else if (this.customAttributeData[offset]==0x54)
{
//Property
++offset;
RPropertyDef property = new RPropertyDef();
property.DeclaringType = this.AttributeConstructor.DeclaringType;
ElementType FieldOrPropType = (ElementType)this.customAttributeData[offset];
switch (FieldOrPropType)
{
case ElementType.Boolean:
property.PropertyType = this.rAssemblyDef.GetRTypeRef(typeof(System.Boolean));
break;
case ElementType.Char:
property.PropertyType = this.rAssemblyDef.GetRTypeRef(typeof(System.Char));
break;
case ElementType.I1:
property.PropertyType = this.rAssemblyDef.GetRTypeRef(typeof(System.SByte));
break;
case ElementType.I2:
property.PropertyType = this.rAssemblyDef.GetRTypeRef(typeof(System.Int16));
break;
case ElementType.I4:
property.PropertyType = this.rAssemblyDef.GetRTypeRef(typeof(System.Int32));
break;
case ElementType.I8:
property.PropertyType = this.rAssemblyDef.GetRTypeRef(typeof(System.Int64));
break;
case ElementType.U1:
property.PropertyType = this.rAssemblyDef.GetRTypeRef(typeof(System.Byte));
break;
case ElementType.U2:
property.PropertyType = this.rAssemblyDef.GetRTypeRef(typeof(System.UInt16));
break;
case ElementType.U4:
property.PropertyType = this.rAssemblyDef.GetRTypeRef(typeof(System.UInt32));
break;
case ElementType.U8:
property.PropertyType = this.rAssemblyDef.GetRTypeRef(typeof(System.UInt64));
break;
case ElementType.R4:
property.PropertyType = this.rAssemblyDef.GetRTypeRef(typeof(System.Single));
break;
case ElementType.R8:
property.PropertyType = this.rAssemblyDef.GetRTypeRef(typeof(System.Double));
break;
case ElementType.String:
property.PropertyType = this.rAssemblyDef.GetRTypeRef(typeof(System.String));
break;
case ElementType.Type:
property.PropertyType = this.rAssemblyDef.GetRTypeRef(typeof(System.Type));
break;
case ElementType.Enum:
++offset;
stringSize = MetadataSignatures.ReadCompressedInt(this.customAttributeData, out offset,offset);
data_array = new byte[stringSize];
for (int x=offset; x< stringSize+offset ; x++)
data_array[x-offset] = this.customAttributeData[x];
name = Encoding.UTF8.GetString(data_array);
property.PropertyType = this.rAssemblyDef.GetRTypeRef(name);
if (property.PropertyType==null)
property.PropertyType = this.rAssemblyDef.RModuleDef.GetType(name);
offset += stringSize - 1;
break;
}
++offset;
stringSize = MetadataSignatures.ReadCompressedInt(this.customAttributeData, out offset,offset);
data_array = new byte[stringSize];
for (int x=offset; x< stringSize+offset ; x++)
data_array[x-offset] = this.customAttributeData[x];
name = Encoding.UTF8.GetString(data_array);
property.Name = name;
offset += stringSize;
if (property.PropertyType.IsArray)
{
int arraySize = LEBitConverter.ToInt32(this.customAttributeData,offset);
offset += 4;
object [] objectArray = new object[arraySize];
for (int x=0; x<arraySize; x++)
{
objectArray[x] = GetElem(property.PropertyType,this.customAttributeData,out offset,offset);
}
this.propertyValues.Add(objectArray);
}
else
{
this.propertyValues.Add(GetElem(property.PropertyType,this.customAttributeData,out offset,offset));
}
this.customAttributeProp.Add(property);
}else
throw new InvalidProgramException("Unknown NamedArg");
}
}
}
}
private ElemType GetElemType(RParameter rParameter,byte [] stream, out int pos, int posValue)
{
return GetElemType(rParameter.ParameterType,stream,out pos,posValue);
}
private ElemType GetElemType(RType rParameterType,byte [] stream, out int pos, int posValue)
{
pos = posValue;
if (rParameterType == null)
throw new NullReferenceException();
if (rParameterType.NameWithNameSpace.Equals("System.String") ||
rParameterType.NameWithNameSpace.Equals("System.Type"))
return ElemType.StringOrType;
// ElementType FieldOrPropType = (ElementType)stream[pos];
// switch (FieldOrPropType)
// {
// case ElementType.Boolean:
// case ElementType.Char:
// case ElementType.I1:
// case ElementType.I2:
// case ElementType.I4:
// case ElementType.I8:
// case ElementType.U1:
// case ElementType.U2:
// case ElementType.U4:
// case ElementType.U8:
// case ElementType.R4:
// case ElementType.R8:
// case ElementType.String:
// case ElementType.Type:
// return ElemType.BoxedValueType;
// }
return ElemType.SimpleOrEnum;
}
private Object GetElem(RParameter parameter,byte [] stream, out int pos, int posValue)
{
return GetElem(parameter.ParameterType,stream,out pos,posValue);
}
private Object GetElem(RType parameterType,byte [] stream, out int pos, int posValue)
{
pos = posValue;
int inc = 0;
int stringSize = 0;
byte[] data_array;
Type t;
switch (GetElemType(parameterType,stream, out pos,pos))
{
case ElemType.SimpleOrEnum:
#region SimpleOrEnum
if (parameterType.NameWithNameSpace.Equals("System.Boolean"))
{
if (stream[pos]==0x00)
{
++pos;
return false;
}
else if (stream[pos]==0x01)
{
++pos;
return true;
}
else
throw new InvalidOperationException("Not a bool values");
}
else if (parameterType.NameWithNameSpace.Equals("System.Char"))
{
++pos;
return (char)stream[pos-1];
}
else if (parameterType.NameWithNameSpace.Equals("System.Single"))
{
Single s = BitConverter.ToSingle(stream,pos);
pos += 4;
return s;
}
else if (parameterType.NameWithNameSpace.Equals("System.Double"))
{
Double d = BitConverter.ToDouble(stream,pos);
pos += 8;
return d;
}
else if (parameterType.NameWithNameSpace.Equals("System.Int16"))
{
inc = 2;
pos += inc;
return LEBitConverter.ToInt16(stream,pos - inc);
}
else if (parameterType.NameWithNameSpace.Equals("System.Int32"))
{
inc = 4;
pos += inc;
return LEBitConverter.ToInt32(stream,pos - inc);
}
else if (parameterType.NameWithNameSpace.Equals("System.Int64"))
{
inc = 8;
pos += inc;
return LEBitConverter.ToInt64(stream,pos - inc);
}
else if (parameterType.NameWithNameSpace.Equals("System.UInt16"))
{
inc = 2;
pos += inc;
return LEBitConverter.ToUInt16(stream,pos - inc);
}
else if (parameterType.NameWithNameSpace.Equals("System.UInt32"))
{
inc = 4;
pos += inc;
return LEBitConverter.ToUInt32(stream,pos - inc);
}
else if (parameterType.NameWithNameSpace.Equals("System.UInt64"))
{
inc = 8;
pos += inc;
return LEBitConverter.ToUInt64(stream,pos - inc);
}
else
{
RType rt = rAssemblyDef.RModuleDef.GetType(parameterType.NameWithNameSpace);
RField f;
if (rt==null)
{
//Type enumType = Type.GetType(parameterType.NameWithNameSpace);
//rt = new RTypeRef(enumType.Name,enumType.Namespace,this.rAssemblyDef);
//((RTypeRef)rt).CompleteRTypeRef(enumType,this.rAssemblyDef);
rt = this.rAssemblyDef.GetRTypeRef(parameterType.NameWithNameSpace);
f = ((RTypeRef)rt).GetField("value__");
}else
f = rt.GetField("value__");
RType fieldType = f.FieldType;
if (fieldType.NameWithNameSpace.Equals("System.Boolean"))
{
if (stream[pos]==0x00)
{
++pos;
return false;
}
else if (stream[pos]==0x01)
{
++pos;
return true;
}
else
throw new InvalidOperationException("Not a bool values");
}
else if (fieldType.NameWithNameSpace.Equals("System.Char"))
{
++pos;
return (char)stream[pos-1];
}
else if (fieldType.NameWithNameSpace.Equals("System.Single"))
{
Single s = BitConverter.ToSingle(stream,pos);
pos += 4;
return s;
}
else if (fieldType.NameWithNameSpace.Equals("System.Double"))
{
Double d = BitConverter.ToDouble(stream,pos);
pos += 8;
return d;
}
else if (fieldType.NameWithNameSpace.Equals("System.Int16"))
{
inc = 2;
pos += inc;
return LEBitConverter.ToInt16(stream,pos - inc);
}
else if (fieldType.NameWithNameSpace.Equals("System.Int32"))
{
inc = 4;
pos += inc;
return LEBitConverter.ToInt32(stream,pos - inc);
}
else if (fieldType.NameWithNameSpace.Equals("System.Int64"))
{
inc = 8;
pos += inc;
return LEBitConverter.ToInt64(stream,pos - inc);
}
else if (fieldType.NameWithNameSpace.Equals("System.UInt16"))
{
inc = 2;
pos += inc;
return LEBitConverter.ToUInt16(stream,pos - inc);
}
else if (fieldType.NameWithNameSpace.Equals("System.UInt32"))
{
inc = 4;
pos += inc;
return LEBitConverter.ToUInt32(stream,pos - inc);
}
else if (fieldType.NameWithNameSpace.Equals("System.UInt64"))
{
inc = 8;
pos += inc;
return LEBitConverter.ToUInt64(stream,pos - inc);
}
else
throw new InvalidProgramException("Not a valid type");
}
#endregion
case ElemType.StringOrType:
#region StringOrType
if (parameterType.NameWithNameSpace.Equals("System.String"))
{
stringSize = MetadataSignatures.ReadCompressedInt(this.customAttributeData, out pos,pos);
data_array = new byte[stringSize];
for (int j=pos; j< stringSize+pos ; j++)
data_array[j-pos] = stream[j];
pos += stringSize;
return Encoding.UTF8.GetString(data_array);
}
else if (parameterType.NameWithNameSpace.Equals("System.Type"))
{
stringSize = MetadataSignatures.ReadCompressedInt(this.customAttributeData, out pos,pos);
data_array = new byte[stringSize];
for (int j=pos; j< stringSize+pos ; j++)
data_array[j-pos] = stream[j];
string typeName = Encoding.UTF8.GetString(data_array);
pos += stringSize;
RType rt;
if (typeName.IndexOf(",")>=0)
{
t = Type.GetType(typeName);
rt = this.rAssemblyDef.GetRTypeRef(t);
return rt;
}
t = Type.GetType(typeName);
if (t == null)
rt = this.rAssemblyDef.RModuleDef.GetType(typeName);
else
rt = this.rAssemblyDef.GetRTypeRef(t);
//pos += stringSize;
return rt;
}
#endregion
break;
case ElemType.BoxedValueType:
#region boxedValueType
ElementType FieldOrPropType = (ElementType)stream[pos];
++pos;
switch (FieldOrPropType)
{
case ElementType.Boolean:
if (stream[pos]==0x00)
{
++pos;
return false;
}
else if (stream[pos]==0x01)
{
++pos;
return true;
}
else
throw new InvalidOperationException("Not a bool values");
case ElementType.Char:
++pos;
return (char)stream[pos-1];
case ElementType.I1:
pos += 1;
return (int)stream[pos - 1];
case ElementType.I2:
pos += 2;
return LEBitConverter.ToInt16(stream, pos - 2);
case ElementType.I4:
pos += 4;
return LEBitConverter.ToInt32(stream, pos - 4);
case ElementType.I8:
pos += 8;
return LEBitConverter.ToInt64(stream, pos - 8);
case ElementType.U1:
pos += 1;
return (int)stream[pos - 1];
case ElementType.U2:
pos += 2;
return LEBitConverter.ToUInt16(stream, pos - 2);
case ElementType.U4:
pos += 4;
return LEBitConverter.ToUInt32(stream, pos - 4);
case ElementType.U8:
pos += 8;
return LEBitConverter.ToUInt64(stream, pos - 8);
case ElementType.R4:
pos += 4;
return BitConverter.ToSingle(stream,pos - 4);
case ElementType.R8:
pos += 8;
return BitConverter.ToSingle(stream,pos - 8);
case ElementType.String:
stringSize = MetadataSignatures.ReadCompressedInt(this.customAttributeData, out pos,pos);
data_array = new byte[stringSize];
for (int j=pos; j< stringSize+pos ; j++)
data_array[j-pos] =stream[j];
pos += stringSize;
return Encoding.UTF8.GetString(data_array);
case ElementType.Type:
stringSize = MetadataSignatures.ReadCompressedInt(this.customAttributeData, out pos,pos);
data_array = new byte[stringSize];
for (int j=pos; j< stringSize+pos ; j++)
data_array[j-pos] = stream[j];
string typeName = Encoding.UTF8.GetString(data_array);
pos += stringSize;
RType rt;
if (typeName.IndexOf(",")>=0)
{
t = Type.GetType(typeName);
rt = this.rAssemblyDef.GetRTypeRef(t);
return rt;
}
t = Type.GetType(typeName);
if (t == null)
rt = this.rAssemblyDef.RModuleDef.GetType(typeName);
else
rt = this.rAssemblyDef.GetRTypeRef(t);
return rt;
}
#endregion
break;
}
throw new NullReferenceException("Argument not found");
}
private enum ElemType
{
SimpleOrEnum,
StringOrType,
BoxedValueType
}
/// <summary>
///
/// </summary>
/// <param name="customAttributeCtor"></param>
/// <param name="ctorArgs"></param>
/// <param name="customAttributeProp"></param>
/// <param name="propertyValues"></param>
/// <param name="customAttributeFields"></param>
/// <param name="fieldsValues"></param>
// public RCustomAttrib(RConstructor customAttributeCtor, Object ctorArgs,
// RProperty[] customAttributeProp, Object[] propertyValues,
// RField[] customAttributeFields, Object[] fieldsValues)
// {
// this.customAttributeCtor = customAttributeCtor;
// this.ctorArgs = ctorArgs;
// this.customAttributeProp = customAttributeProp;
// this.propertyValues = propertyValues;
// this.customAttributeFields = customAttributeFields;
// this.fieldsValues = fieldsValues;
// }
/// <summary>
/// Gets or sets the constructor used to create the custom attribute.
/// </summary>
public RConstructor AttributeConstructor
{
get
{
return this.customAttributeCtor;
}
set
{
this.customAttributeCtor = value;
}
}
/// <summary>
/// Gets or sets the data used to create the custom attribute.
/// </summary>
public byte [] AttributeData
{
get
{
return this.customAttributeData;
}
set
{
this.customAttributeData = value;
}
}
/// <summary>
/// Returns the type of the custom attribute represented by this object.
/// This is obtained from the constructor and is changed only when the
/// constructor is changed.
/// </summary>
public RType CustomAttributeType
{
get
{
return this.customAttributeCtor.DeclaringType;
}
}
/// <summary>
/// Gets the constructor arguments. The constructor will be called with
/// these arguments when the assembly containing this attribute is
/// created.
/// </summary>
/// <returns></returns>
public Object[] GetAttributeConstructorArguments()
{
return this.constructorArguments;
}
/// <summary>
/// Sets the constructor arguments.
/// </summary>
/// <param name="args"></param>
public void SetAttributeConstructorArguments(Object[] args)
{
this.constructorArguments = args;
}
/// <summary>
/// Get the properties array
/// </summary>
/// <returns></returns>
public RProperty [] GetProperties()
{
if (this.customAttributeProp==null)
return null;
RProperty [] rp = new RProperty[this.customAttributeProp.Count];
int i = 0;
while (i<this.customAttributeProp.Count)
{
rp[i] = this.customAttributeProp[i] as RProperty;
++i;
}
return rp;
}
/// <summary>
/// Get the fields array
/// </summary>
/// <returns></returns>
public RField [] GetFields()
{
if (this.customAttributeFields==null)
return null;
RField [] rf = new RField[this.customAttributeFields.Count];
int i = 0;
while (i<this.customAttributeFields.Count)
{
rf[i] = this.customAttributeFields[i] as RField;
++i;
}
return rf;
}
/// <summary>
/// Get values for the properties
/// </summary>
/// <returns></returns>
public Object [] GetPropertiesValues()
{
if (this.propertyValues==null)
return null;
Object [] obj = new Object[this.propertyValues.Count];
int i = 0;
while (i<this.propertyValues.Count)
{
obj[i] = this.propertyValues[i] as Object;
++i;
}
return obj;
}
/// <summary>
/// Get values for the fields
/// </summary>
/// <returns></returns>
public Object [] GetFieldsValues()
{
if (this.fieldsValues==null)
return null;
Object [] obj = new Object[this.fieldsValues.Count];
int i = 0;
while (i<this.fieldsValues.Count)
{
obj[i] = this.fieldsValues[i] as Object;
++i;
}
return obj;
}
/// <summary>
/// Set the Properties list
/// </summary>
/// <param name="props"></param>
public void SetProperties(RProperty [] props)
{
if (props!=null)
{
int i = 0;
while(i<props.Length)
{
this.customAttributeProp.Add(props[i]);
++i;
}
}
}
/// <summary>
/// Set the fields list
/// </summary>
/// <param name="props"></param>
public void SetProperties(RField [] fields)
{
if (fields!=null)
{
int i = 0;
while(i<fields.Length)
{
this.customAttributeFields.Add(fields[i]);
++i;
}
}
}
public void SetPropertiesValues(Object [] values)
{
if (values!=null)
{
int i = 0;
while(i<values.Length)
{
this.propertyValues.Add(values[i]);
++i;
}
}
}
public void SetFieldsValues(Object [] values)
{
if (values!=null)
{
int i = 0;
while(i<values.Length)
{
this.fieldsValues.Add(values[i]);
++i;
}
}
}
/// <summary>
/// Obtains the value used to initialize of the given field. The field
/// must belong to the underlying attribute
/// </summary>
/// <param name="cAttrField"></param>
/// <returns></returns>
// public Object GetFieldValue(RField customAttrField)
// {
// if (this.customAttributeFields==null) return null;
// if (this.fieldsValues==null) return null;
// RField r = null;
// for (int i = 0; i < this.customAttributeFields.Count;i++)
// {
// r = (RField)this.customAttributeFields[i];
// if (r.Equals(customAttrField))
// {
// if (this.fieldsValues.Count>i)
// return this.fieldsValues[i];
// else
// return null;
// }
// }
// return null;
// }
/// <summary>
/// Sets the value used to initialize the given field.
/// </summary>
/// <param name="cAttrField"></param>
/// <param name="fieldValue"></param>
// public void SetFieldValue(RField customAttrField, Object fieldValue)
// {
// if (this.customAttributeFields==null) return;
// RField r = null;
// for (int i = 0; i < this.customAttributeFields.Count;i++)
// {
// r = (RField)this.customAttributeFields[i];
// if (r.Equals(customAttrField))
// {
// if (this.fieldsValues==null)
// this.fieldsValues = new Object[this.customAttributeFields.Count];
// if (this.fieldsValues.Count<this.customAttributeFields.Length)
// {
// Object [] temp = new Object[this.customAttributeFields.Count];
// for (int j = 0; j< this.fieldsValues.Count;j++)
// temp[j] = this.fieldsValues[j];
// this.fieldsValues = temp;
// }
// this.fieldsValues[i] = fieldValue;
// }
// }
//
// }
/// <summary>
/// Gets the value used to initialize a certain property of the custom attribute.
/// </summary>
/// <param name="cAttrProperty"></param>
/// <returns></returns>
// public Object GetPropertyValue(RProperty customAttrProperty)
// {
// if (this.customAttributeProp==null) return null;
// if (this.propertyValues==null) return null;
// RProperty r = null;
// for (int i = 0; i < this.customAttributeProp.Length;i++)
// {
// r = this.customAttributeProp[i];
// if (r.Equals(customAttrProperty))
// {
// if (this.propertyValues.Length>i)
// return this.propertyValues[i];
// else
// return null;
// }
// }
// return null;
// }
/// <summary>
/// Sets the value used to initialize a certain property of the custom attribute.
/// </summary>
/// <param name="cAttrProperty"></param>
/// <param name="propertyValue"></param>
// public void SetPropertyValue(RProperty customAttrProperty, Object propertyValue)
// {
// if (this.customAttributeProp==null) return;
// RProperty r = null;
// for (int i = 0; i < this.customAttributeProp.Length;i++)
// {
// r = this.customAttributeProp[i];
// if (r.Equals(customAttrProperty))
// {
// if (this.propertyValues==null)
// this.propertyValues = new Object[this.customAttributeProp.Length];
// if (this.propertyValues.Length<this.customAttributeProp.Length)
// {
// Object [] temp = new Object[this.customAttributeProp.Length];
// for (int j = 0; j< this.propertyValues.Length;j++)
// temp[j] = this.propertyValues[j];
// this.propertyValues = temp;
// }
// this.propertyValues[i] = propertyValue;
// }
// }
// }
}
/// <summary>
/// Represents an element that can have custom attributes.
/// </summary>
/// <remarks>
/// </remarks>
public interface ICustomAttributeOwner
{
#region ICustomAttributeProvider Methods
/// <summary>
/// Gets an array with all custom attributes of defined on this member.
/// </summary>
/// <param name="inherit">Whether the hierarchy chain should be searched for
/// custom attributes</param>
/// <returns>An array with all the custom attributes defined on this
/// member.</returns>
RCustomAttrib[] GetCustomAttributes(bool inherit);
/// <summary>
/// Gets an array with all custom attributes of <i>attributeType</i> defined
/// on this member.
/// </summary>
/// <param name="attributeType">The type of the custom attribute</param>
/// <param name="inherit">Whether the hierarchy chain should be searched for the
/// custom attribute</param>
/// <returns>An array with all the custom attributes defined on this member.</returns>
RCustomAttrib[] GetCustomAttributes(RType attributeType, bool inherit);
/// <summary>
/// Indicates whether one or more instance of attribute type is defined
/// on this member.
/// </summary>
/// <param name="attributeType">The type of the custom attribute</param>
/// <param name="inherit">Whether the attribute should be searched in the
/// hierarchy chain</param>
/// <returns><i>True</i> if the attribute is defined on this member.</returns>
bool IsDefined(RType attributeType,bool inherit);
#endregion
}
/// <summary>
/// To be implemented by the Ref classes.
/// </summary>
public interface ICustomAttributeOwnerDef : ICustomAttributeOwner
{
/// <summary>
/// Adds a custom attribute to this element
/// </summary>
/// <param name="attribute">The attribute to be added.</param>
void AddCustomAttributtes(RCustomAttrib attribute);
/// <summary>
/// Removes the given custom attribute instance from this member.
/// </summary>
/// <param name="attribute">The instance of the custom attribute to
/// be removed.</param>
/// <remarks>If the given attribute is not found, this method returns
/// silently.</remarks>
void RemoveCustomAttribute(RCustomAttrib attribute);
}
/// <summary>
///
/// </summary>
public abstract class CustomAttributeOwner : ICustomAttributeOwner
{
#region fields
/// <summary>
///
/// </summary>
private ArrayList customAttributes;
/// <summary>
///
/// </summary>
private IEnumerator iEnum;
#endregion
/// <summary>
///
/// </summary>
/// <param name="inherit"></param>
/// <returns></returns>
public virtual RCustomAttrib[] GetCustomAttributes(bool inherit)
{
if (inherit)
throw new NotImplementedException();
if (customAttributes==null)
return new RCustomAttrib[0];
RCustomAttrib [] rCAttribs = new RCustomAttrib[customAttributes.Count];
int i = 0;
foreach (RCustomAttrib r in customAttributes)
{
rCAttribs[i] = r;
++i;
}
return rCAttribs;
}
/// <summary>
///
/// </summary>
/// <param name="attributeType"></param>
/// <param name="inherit"></param>
/// <returns></returns>
public virtual RCustomAttrib[] GetCustomAttributes(String attributeType, bool inherit)
{
if (inherit)
throw new NotImplementedException();
if (customAttributes==null)
return new RCustomAttrib[0];
RCustomAttrib [] rCAttribs = new RCustomAttrib[customAttributes.Count];
int i = 0;
foreach (RCustomAttrib r in customAttributes)
{
if (r.CustomAttributeType.NameWithNameSpace.Equals(attributeType))
{
rCAttribs[i] = r;
++i;
}
}
RCustomAttrib [] temp = new RCustomAttrib[i];
for(int j = 0; j < i; j++)
{
temp[j] = rCAttribs[j];
}
return temp;
}
/// <summary>
///
/// </summary>
/// <param name="attributeType"></param>
/// <param name="inherit"></param>
/// <returns></returns>
public virtual RCustomAttrib[] GetCustomAttributes(RType attributeType, bool inherit)
{
if (inherit)
throw new NotImplementedException();
if (customAttributes==null)
return new RCustomAttrib[0];
RCustomAttrib [] rCAttribs = new RCustomAttrib[customAttributes.Count];
int i = 0;
foreach (RCustomAttrib r in customAttributes)
{
if (r.CustomAttributeType.NameWithNameSpace.Equals(attributeType.NameWithNameSpace))
{
rCAttribs[i] = r;
++i;
}
}
RCustomAttrib [] temp = new RCustomAttrib[i];
for(int j = 0; j < i; j++)
{
temp[j] = rCAttribs[j];
}
return temp;
}
/// <summary>
///
/// </summary>
/// <param name="attributeType"></param>
/// <param name="inherit"></param>
/// <returns></returns>
public virtual bool IsDefined(RType attributeType,bool inherit)
{
if (inherit)
throw new NotImplementedException();
bool retVal = false;
foreach (RCustomAttrib r in customAttributes)
{
if (r.CustomAttributeType.Equals(attributeType))
{
retVal = true;
break;
}
}
return retVal;
}
/// <summary>
/// Adds a custom attribute to this element
/// </summary>
/// <param name="attribute">The attribute to be added.</param>
protected internal void InternalAddCustomAttributtes(RCustomAttrib attribute)
{
if (this.customAttributes==null)
this.customAttributes = new ArrayList();
this.customAttributes.Add(attribute);
this.iEnum = this.customAttributes.GetEnumerator();
}
/// <summary>
/// Removes the given custom attribute instance from this member.
/// </summary>
/// <param name="attribute">The instance of the custom attribute to
/// be removed.</param>
/// <remarks>If the given attribute is not found, this method returns
/// silently.</remarks>
protected internal void InternalRemoveCustomAttribute(RCustomAttrib attribute)
{
if (this.customAttributes!=null)
if (this.customAttributes.Contains(attribute))
this.customAttributes.Remove(attribute);
this.iEnum = this.customAttributes.GetEnumerator();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
protected internal bool MoveToNextCustomAttribute()
{
if (this.customAttributes==null) return false;
if (this.iEnum == null)
this.iEnum = this.customAttributes.GetEnumerator();
return this.iEnum.MoveNext();
}
/// <summary>
///
/// </summary>
protected internal RCustomAttrib CurrentCustomAttribute
{
get
{
if (this.customAttributes==null) return null;
if (this.iEnum == null) {
this.iEnum = this.customAttributes.GetEnumerator();
this.iEnum.MoveNext();
}
return (RCustomAttrib)this.iEnum.Current;
}
}
/// <summary>
///
/// </summary>
protected internal int CustomAttributeCount
{
get
{
if (this.customAttributes==null) return 0;
return this.customAttributes.Count;
}
}
}
}
|