Почему не находит поле System.FieldAccessException при создании динамического метода?

Системное исключение System.FieldAccessException возникает, когда пытаетесь получить доступ к полю, которое недоступно из текущего контекста выполнения. Это может быть вызвано установленными уровнями защиты или ограничениями на доступ к полю.

При создании динамического метода в C# можно использовать класс System.Reflection.Emit.MethodBuilder или класс System.Reflection.Emit.DynamicMethod. Оба эти класса позволяют создавать методы на лету, динамически во время выполнения программы.

Однако, при использовании метода System.Reflection.Emit.MethodBuilder, по умолчанию применяется проверка полей для доступа к закрытым и защищенным полям. То есть, если вы пытаетесь получить доступ к закрытым или защищенным полям, то будет выброшено исключение System.FieldAccessException.

Вот пример кода, который может вызвать исключение System.FieldAccessException:

using System;
using System.Reflection;
using System.Reflection.Emit;

public class Program
{
    private int privateField;

    public static void Main()
    {
        TypeBuilder typeBuilder = GetTypeBuilder();
        MethodBuilder methodBuilder = typeBuilder.DefineMethod("MyMethod", MethodAttributes.Public | MethodAttributes.Static);

        ILGenerator ilGenerator = methodBuilder.GetILGenerator();
        ilGenerator.Emit(OpCodes.Ldarg_0);
        FieldInfo fieldInfo = typeof(Program).GetField("privateField", BindingFlags.NonPublic | BindingFlags.Instance);
        ilGenerator.Emit(OpCodes.Stfld, fieldInfo);
        ilGenerator.Emit(OpCodes.Ret);

        Type createdType = typeBuilder.CreateType();
        createdType.GetMethod("MyMethod").Invoke(null, null);
    }

    private static TypeBuilder GetTypeBuilder()
    {
        var typeSignature = "MyDynamicType";
        var an = new AssemblyName(typeSignature);
        AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
        ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
        TypeBuilder tb = moduleBuilder.DefineType(typeSignature,
                TypeAttributes.Public |
                TypeAttributes.Class |
                TypeAttributes.AutoClass |
                TypeAttributes.AnsiClass |
                TypeAttributes.BeforeFieldInit |
                TypeAttributes.AutoLayout,
                null);
        return tb;
    }
}

В этом примере создается динамический метод "MyMethod", который пытается получить доступ к полю "privateField". Если попытаться выполнить этот пример, то будет выброшено исключение System.FieldAccessException.

Чтобы решить эту проблему и избежать исключения System.FieldAccessException, необходимо изменить доступ к полю с private на public или protected, или использовать метод System.Reflection.Emit.DynamicMethod, который не применяет проверку на доступ к полям.

Вот пример кода, который использует System.Reflection.Emit.DynamicMethod и не вызовет исключение System.FieldAccessException:

using System;
using System.Reflection;
using System.Reflection.Emit;

public class Program
{
    private int privateField;

    public static void Main()
    {
        DynamicMethod dynamicMethod = new DynamicMethod("MyMethod", null, new Type[] { typeof(object) });
        ILGenerator ilGenerator = dynamicMethod.GetILGenerator();
        ilGenerator.Emit(OpCodes.Ldarg_0);
        FieldInfo fieldInfo = typeof(Program).GetField("privateField", BindingFlags.NonPublic | BindingFlags.Instance);
        ilGenerator.Emit(OpCodes.Stfld, fieldInfo);
        ilGenerator.Emit(OpCodes.Ret);

        Action<object> action = (Action<object>)dynamicMethod.CreateDelegate(typeof(Action<object>));
        action(null);
    }
}

В этом примере создается динамический метод "MyMethod", который также пытается получить доступ к полю "privateField". Однако, использование System.Reflection.Emit.DynamicMethod не вызывает исключение System.FieldAccessException, потому что он не применяет проверку на доступ к полям.