private static ValueSetter CreateSetter(TagFieldInfo tagFieldInfo) { var ownerType = tagFieldInfo.DeclaringType; var valueType = tagFieldInfo.FieldType; if (ownerType.IsGenericTypeDefinition) { ownerType = ownerType.MakeGenericType(valueType); } // Parameter "target", the object on which to set the field `field`. var ownerParam = Expression.Parameter(typeof(object)); // Parameter "value" the value to be set in the `field` on "target". var valueParam = Expression.Parameter(typeof(object)); // Unbox structs to their type, or cast a class to it's type. var castTartgetExp = ownerType.IsValueType ? Expression.Unbox(ownerParam, ownerType) : Expression.Convert(ownerParam, ownerType); // Cast the value to its correct type. var castValueExp = Expression.Convert(valueParam, valueType); // Access the field var fieldExp = Expression.Field(castTartgetExp, tagFieldInfo.FieldInfo); // Assign the "value" to the `field`. var assignExp = Expression.Assign(fieldExp, castValueExp); // Compile the whole thing and return. var setter = Expression.Lambda <ValueSetter>(assignExp, ownerParam, valueParam).Compile(); return(setter); }
private static ValueGetter CreateGetter(TagFieldInfo tagFieldInfo) { var ownerType = tagFieldInfo.DeclaringType; // Parameter "owner", the object on which to get the field value from. ParameterExpression ownerParam = Expression.Parameter(typeof(object)); // Unbox structs to their type, or cast a class to it's type. Expression castTartgetExp = ownerType.IsValueType ? Expression.Unbox(ownerParam, ownerType) : Expression.Convert(ownerParam, ownerType); // Access the field MemberExpression fieldExp = Expression.Field(castTartgetExp, tagFieldInfo.FieldInfo); // Convert field to object Type UnaryExpression boxedExp = Expression.Convert(fieldExp, typeof(object)); var getter = Expression.Lambda <ValueGetter>(boxedExp, ownerParam).Compile(); return(getter); }
/// <summary> /// Gets the size of a tag-field. /// </summary> /// <param name="type">The <see cref="Type"/> of the field.</param> /// <param name="attr">The <see cref="TagFieldAttribute"/> of the field.</param> /// <param name="targetVersion">The <see cref="CacheVersion"/> to target.</param> /// <returns></returns> public static uint GetFieldSize(Type type, TagFieldAttribute attr, CacheVersion targetVersion) { switch (Type.GetTypeCode(type)) { case TypeCode.Boolean: case TypeCode.SByte: case TypeCode.Byte: return(0x01); case TypeCode.Char: case TypeCode.Int16: case TypeCode.UInt16: return(0x02); case TypeCode.Single: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Object when attr != null && attr.Flags.HasFlag(TagFieldFlags.Pointer): case TypeCode.Object when type == typeof(Tag): case TypeCode.Object when type == typeof(CacheAddress): case TypeCode.Object when type == typeof(CachedTagInstance) && attr.Flags.HasFlag(TagFieldFlags.Short): //case TypeCode.Object when type == typeof(RgbColor): case TypeCode.Object when type == typeof(ArgbColor): case TypeCode.Object when type == typeof(Point2d): case TypeCode.Object when type == typeof(StringId): case TypeCode.Object when type == typeof(Angle): case TypeCode.Object when type == typeof(VertexShaderReference): case TypeCode.Object when type == typeof(PixelShaderReference): return(0x04); case TypeCode.Double: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Object when type == typeof(CachedTagInstance) && targetVersion != CacheVersion.Unknown && CacheVersionDetection.IsBetween(targetVersion, CacheVersion.Halo2Xbox, CacheVersion.Halo2Vista): case TypeCode.Object when type == typeof(byte[]) && targetVersion != CacheVersion.Unknown && CacheVersionDetection.IsBetween(targetVersion, CacheVersion.Halo2Xbox, CacheVersion.Halo2Vista): case TypeCode.Object when type == typeof(Rectangle2d): case TypeCode.Object when type == typeof(RealEulerAngles2d): case TypeCode.Object when type == typeof(RealPoint2d): case TypeCode.Object when type == typeof(RealVector2d): case TypeCode.Object when type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List <>) && targetVersion != CacheVersion.Unknown && CacheVersionDetection.IsBetween(targetVersion, CacheVersion.Halo2Xbox, CacheVersion.Halo2Vista): case TypeCode.Object when type.IsGenericType && type.GetGenericTypeDefinition() == typeof(TagBlock <>) && targetVersion != CacheVersion.Unknown && CacheVersionDetection.IsBetween(targetVersion, CacheVersion.Halo2Xbox, CacheVersion.Halo2Vista): return(0x08); case TypeCode.Object when type == typeof(RealRgbColor): case TypeCode.Object when type == typeof(RealEulerAngles3d): case TypeCode.Object when type == typeof(RealPoint3d): case TypeCode.Object when type == typeof(RealVector3d): case TypeCode.Object when type == typeof(RealPlane2d): case TypeCode.Object when type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List <>) && CacheVersionDetection.IsBetween(targetVersion, CacheVersion.Halo3Retail, CacheVersion.Unknown): case TypeCode.Object when type.IsGenericType && type.GetGenericTypeDefinition() == typeof(TagBlock <>) && CacheVersionDetection.IsBetween(targetVersion, CacheVersion.Halo3Retail, CacheVersion.Unknown): return(0x0C); case TypeCode.Decimal: case TypeCode.Object when type == typeof(CachedTagInstance) && CacheVersionDetection.IsBetween(targetVersion, CacheVersion.Halo3Retail, CacheVersion.Unknown): case TypeCode.Object when type == typeof(RealArgbColor): case TypeCode.Object when type == typeof(RealQuaternion): case TypeCode.Object when type == typeof(RealPlane3d): return(0x10); case TypeCode.Object when type == typeof(byte[]) && CacheVersionDetection.IsBetween(targetVersion, CacheVersion.Halo3Retail, CacheVersion.Unknown): return(0x14); case TypeCode.Object when type == typeof(RealMatrix4x3): return(0x30); case TypeCode.Object when type == typeof(DatumIndex): return(sizeof(uint)); case TypeCode.String: case TypeCode.Object when type.IsArray: return((uint)attr.Length); case TypeCode.Object when type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Bounds <>): return(TagFieldInfo.GetFieldSize(type.GenericTypeArguments[0], attr, targetVersion) * 2); case TypeCode.Object when type.IsEnum: return(TagFieldInfo.GetFieldSize(type.GetEnumUnderlyingType(), attr, targetVersion)); // Assume the field is a structure default: return(TagStructure.GetTagStructureInfo(type, targetVersion).TotalSize); } }