Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Reflection.Emit设置静态字段的值在Unity中失败_C#_Unity3d_Reflection.emit - Fatal编程技术网

C# 使用Reflection.Emit设置静态字段的值在Unity中失败

C# 使用Reflection.Emit设置静态字段的值在Unity中失败,c#,unity3d,reflection.emit,C#,Unity3d,Reflection.emit,我正在尝试使用Reflection.Emit设置静态字段的值(我无法访问.NET 4的表达式.Assign,因为我一直使用Unity的.NET 3.5) 我目前的代码如下: public Action<TTarget, TField> GetSetter<TTarget, TField>(FieldInfo fieldInfo) { DynamicMethod setterMethod = new DynamicMethod ( "sett

我正在尝试使用
Reflection.Emit
设置静态字段的值(我无法访问.NET 4的
表达式.Assign
,因为我一直使用Unity的.NET 3.5)

我目前的代码如下:

public Action<TTarget, TField> GetSetter<TTarget, TField>(FieldInfo fieldInfo)
{
    DynamicMethod setterMethod = new DynamicMethod
    (
        "setter",
        typeof(void),
        new Type[] { typeof(TTarget), typeof(TField) },
        typeof(TTarget)
    );

    var setterIL = setterMethod.GetILGenerator();

    if (fieldInfo.IsStatic)
    {
        setterIL.Emit(OpCodes.Ldnull);
    }
    else
    {
        setterIL.Emit(OpCodes.Ldarg_0);
    }

    setterIL.Emit(OpCodes.Ldarg_1);
    setterIL.Emit(OpCodes.Stfld, fieldInfo);
    setterIL.Emit(OpCodes.Ret);

    return (Action<TTarget, TField>)setterMethod.CreateDelegate(typeof(Action<TTarget, TField>));
}
改为使用(设置静态字段):


NET运行时在幕后可能比Mono运行时更宽松(即:它允许
Stfld
,即使是静态字段,只忽略第一个参数,而Mono不允许),这就解释了为什么问题只发生在Unity中。

您确定这就是确切的代码吗
GetSetter
不应编译-不能将静态类型用作类型参数。此外,不需要检查字段是否为静态。由于您的方法要求目标(并且您提供了它:
Invoke(null,123)
),因此您应该始终发出
Ldarg\u 0
。这也会导致有人编写
Invoke(notnullinstance,123)
,这会引发一个错误,但会悄悄地将
123
设置为静态字段。没错,这个类不是静态的,我匆忙地给出了一个简化的示例。根据,您又是对的,
Ldarg_0
应该可以工作,但它不工作。在这种情况下,我无法复制它(复制并粘贴代码而不进行更改),它工作得很好。您正在运行哪个框架版本?你确定这个字段确实是静态的吗?我只是复制并粘贴了我提供的示例代码,然后得到了错误。我在Unity内部使用.NET3.5。
using System;
using System.Reflection;
using System.Reflection.Emit;
using UnityEditor;

class Program
{
    public static Action<TTarget, TField> GetSetter<TTarget, TField>(FieldInfo fieldInfo)
    {
        DynamicMethod setterMethod = new DynamicMethod
        (
            "setter",
            typeof(void),
            new Type[] { typeof(TTarget), typeof(TField) },
            typeof(TTarget)
        );

        var setterIL = setterMethod.GetILGenerator();

        setterIL.Emit(OpCodes.Ldarg_0);
        setterIL.Emit(OpCodes.Ldarg_1);
        setterIL.Emit(OpCodes.Stfld, fieldInfo);
        setterIL.Emit(OpCodes.Ret);

        return (Action<TTarget, TField>)setterMethod.CreateDelegate(typeof(Action<TTarget, TField>));
    }

    public class Static
    {
        public static int x;
    }

    [MenuItem("Tools/Debug IL")]
    static void Debug()
    {
        var fieldInfo = typeof(Static).GetField("x");

        var setter = GetSetter<Static, int>(fieldInfo);

        setter.Invoke(null, 123);

        Debug.Log("Static field assignment succeeded.");
    }
}
using System;
using System.Reflection;
using System.Reflection.Emit;
using UnityEditor;

class Program
{
    public static Action<TTarget, TField> GetSetter<TTarget, TField>(FieldInfo fieldInfo)
    {
        DynamicMethod setterMethod = new DynamicMethod
        (
            "setter",
            typeof(void),
            new Type[] { typeof(TTarget), typeof(TField) },
            typeof(TTarget)
        );

        var setterIL = setterMethod.GetILGenerator();

        setterIL.Emit(OpCodes.Ldarg_0);
        setterIL.Emit(OpCodes.Ldarg_1);
        setterIL.Emit(OpCodes.Stfld, fieldInfo);
        setterIL.Emit(OpCodes.Ret);

        return (Action<TTarget, TField>)setterMethod.CreateDelegate(typeof(Action<TTarget, TField>));
    }

    public class Static
    {
        public static int x;
    }

    [MenuItem("Tools/Debug IL")]
    static void Debug()
    {
        var fieldInfo = typeof(Static).GetField("x");

        var setter = GetSetter<Static, int>(fieldInfo);

        setter.Invoke(null, 123);

        Debug.Log("Static field assignment succeeded.");
    }
}
if (fieldInfo.IsStatic)
{
    setterIL.Emit(OpCodes.Ldarg_0);
    setterIL.Emit(OpCodes.Stsfld, fieldInfo);
    setterIL.Emit(OpCodes.Ret);
}
else
{
    setterIL.Emit(OpCodes.Ldarg_0);
    setterIL.Emit(OpCodes.Ldarg_1);
    setterIL.Emit(OpCodes.Stfld, fieldInfo);
    setterIL.Emit(OpCodes.Ret);
}