Skip to content

UnityEngine.Vector3 serializes but does not deserialize (with fix!) #130

@jhughes2112

Description

@jhughes2112

Here's the error (which was reported previously, but nobody actually solved):

InvalidProgramException: Invalid IL code in (wrapper dynamic-method) FakeVector3:_cgm (object): IL_0013: ret       

System.Delegate.CreateDelegate (System.Type type, System.Object firstArgument, System.Reflection.MethodInfo method, System.Boolean throwOnBindFailure, System.Boolean allowClosed) (at <695d1cc93cca45069c528c15c9fdd749>:0)

Here is some simple test code that shows it broken:

public struct FakeVector3
{
	public float x;
	public float y;
	public float z;

	public static FakeVector3 right { get { return new FakeVector3() { x=1,y=2,z=3 }; } }
}

FakeVector3 v = new FakeVector3() { x=0, y=1, z=2 };
string json = fastJSON.JSON.ToJSON(v);
FakeVector3 newV = fastJSON.JSON.ToObject<FakeVector3>(json);

Basically what is happening is the Reflection.CreateGetMethod() was doing the wrong thing for static getters in structs. Here's how I modified it to work, which does deserialize properly:

        internal static GenericGetter CreateGetMethod(Type type, PropertyInfo propertyInfo)
        {
            MethodInfo getMethod = propertyInfo.GetGetMethod();
            if (getMethod == null)
                return null;

            DynamicMethod getter = new DynamicMethod("_cgm", typeof(object), new Type[] { typeof(object) }, type, true);

            ILGenerator il = getter.GetILGenerator();

            if (!type.IsClass) // structs
            {
                var lv = il.DeclareLocal(type);
		if (!getMethod.IsStatic)
		{
			il.Emit(OpCodes.Ldarg_0);
			il.Emit(OpCodes.Unbox_Any, type);
			il.Emit(OpCodes.Stloc_0);
			il.Emit(OpCodes.Ldloca_S, lv);
			il.EmitCall(OpCodes.Call, getMethod, null);
		}
		else  // call a static method on a struct type
		{
			il.Emit(OpCodes.Call, getMethod);
		}
		if (propertyInfo.PropertyType.IsValueType)
			il.Emit(OpCodes.Box, propertyInfo.PropertyType);
            }
            else
            {
                if (!getMethod.IsStatic)
                {
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
                    il.EmitCall(OpCodes.Callvirt, getMethod, null);
                }
                else
                    il.Emit(OpCodes.Call, getMethod);

                if (propertyInfo.PropertyType.IsValueType)
                    il.Emit(OpCodes.Box, propertyInfo.PropertyType);
            }

            il.Emit(OpCodes.Ret);

            return (GenericGetter)getter.CreateDelegate(typeof(GenericGetter));
        }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions