DotNet
Constant.cs
// dnlib: See LICENSE.txt for more info
using System;
using System.Text;
using dnlib.DotNet.MD;
namespace dnlib.DotNet {
///
/// A high-level representation of a row in the Constant table
///
public abstract clast Constant : IMDTokenProvider {
///
/// The row id in its table
///
protected uint rid;
///
public MDToken MDToken {
get { return new MDToken(Table.Constant, rid); }
}
///
public uint Rid {
get { return rid; }
set { rid = value; }
}
///
/// From column Constant.Type
///
public ElementType Type {
get { return type; }
set { type = value; }
}
///
protected ElementType type;
///
/// From column Constant.Value
///
public object Value {
get { return value; }
set { this.value = value; }
}
///
protected object value;
}
///
/// A Constant row created by the user and not present in the original .NET file
///
public clast ConstantUser : Constant {
///
/// Default constructor
///
public ConstantUser() {
}
///
/// Constructor
///
/// Value
public ConstantUser(object value) {
this.type = GetElementType(value);
this.value = value;
}
///
/// Constructor
///
/// Value
/// Type
public ConstantUser(object value, ElementType type) {
this.type = type;
this.value = value;
}
static ElementType GetElementType(object value) {
if (value == null)
return ElementType.Clast;
switch (System.Type.GetTypeCode(value.GetType())) {
case TypeCode.Boolean: return ElementType.Boolean;
case TypeCode.Char: return ElementType.Char;
case TypeCode.SByte: return ElementType.I1;
case TypeCode.Byte: return ElementType.U1;
case TypeCode.Int16: return ElementType.I2;
case TypeCode.UInt16: return ElementType.U2;
case TypeCode.Int32: return ElementType.I4;
case TypeCode.UInt32: return ElementType.U4;
case TypeCode.Int64: return ElementType.I8;
case TypeCode.UInt64: return ElementType.U8;
case TypeCode.Single: return ElementType.R4;
case TypeCode.Double: return ElementType.R8;
case TypeCode.String: return ElementType.String;
default: return ElementType.Void;
}
}
}
///
/// Created from a row in the Constant table
///
sealed clast ConstantMD : Constant, IMDTokenProviderMD {
readonly uint origRid;
///
public uint OrigRid {
get { return origRid; }
}
///
/// Constructor
///
/// The module which contains this Constant row
/// Row ID
/// If is null
/// If is invalid
public ConstantMD(ModuleDefMD readerModule, uint rid) {
#if DEBUG
if (readerModule == null)
throw new ArgumentNullException("readerModule");
if (readerModule.TablesStream.ConstantTable.IsInvalidRID(rid))
throw new BadImageFormatException(string.Format("Constant rid {0} does not exist", rid));
#endif
this.origRid = rid;
this.rid = rid;
uint value = readerModule.TablesStream.ReadConstantRow(origRid, out this.type);
this.value = GetValue(this.type, readerModule.BlobStream.ReadNoNull(value));
}
static object GetValue(ElementType etype, byte[] data) {
switch (etype) {
case ElementType.Boolean:
if (data == null || data.Length < 1)
return false;
return BitConverter.ToBoolean(data, 0);
case ElementType.Char:
if (data == null || data.Length < 2)
return (char)0;
return BitConverter.ToChar(data, 0);
case ElementType.I1:
if (data == null || data.Length < 1)
return (sbyte)0;
return (sbyte)data[0];
case ElementType.U1:
if (data == null || data.Length < 1)
return (byte)0;
return data[0];
case ElementType.I2:
if (data == null || data.Length < 2)
return (short)0;
return BitConverter.ToInt16(data, 0);
case ElementType.U2:
if (data == null || data.Length < 2)
return (ushort)0;
return BitConverter.ToUInt16(data, 0);
case ElementType.I4:
if (data == null || data.Length < 4)
return (int)0;
return BitConverter.ToInt32(data, 0);
case ElementType.U4:
if (data == null || data.Length < 4)
return (uint)0;
return BitConverter.ToUInt32(data, 0);
case ElementType.I8:
if (data == null || data.Length < 8)
return (long)0;
return BitConverter.ToInt64(data, 0);
case ElementType.U8:
if (data == null || data.Length < 8)
return (ulong)0;
return BitConverter.ToUInt64(data, 0);
case ElementType.R4:
if (data == null || data.Length < 4)
return (float)0;
return BitConverter.ToSingle(data, 0);
case ElementType.R8:
if (data == null || data.Length < 8)
return (double)0;
return BitConverter.ToDouble(data, 0);
case ElementType.String:
if (data == null)
return string.Empty;
return Encoding.Unicode.GetString(data, 0, data.Length / 2 * 2);
case ElementType.Clast:
return null;
default:
return null;
}
}
}
}