У меня есть динамически сгенерированный класс, которому требуется доступ к полю из класса base
.Я продолжаю получать это исключение:
Исключение
System.FieldAccessException: 'Попытка методом' AutoGenRelay.SetAsync (System.String, redius.Cell, System.Nullable`1, redius.SetPolicy) 'для доступа к полю' RediusTests.DaemonBase.IsTransaction 'не удалось.'
Базовый класс :
public abstract class DaemonBase : Abs.Api.IAll,IDisposable {
#region IAll implementation
.......
public abstract Task<Pair> BLPopAsync(IEnumerable<string> keys, TimeSpan? timeout);
......
#endregion
public bool IsTransaction;
public DaemonBase() {
}
public void Dispose() {
throw new NotImplementedException();
}
}
Класс сгенерированный автоматически
class RelayGen : DaemonBase {
public override Task<Pair> BLPopAsync(IEnumerable<string> keys, TimeSpan? timeout) {
if (this.IsTransaction) {
return this.relay.normal.BLPopAsync(keys, timeout);
} else
return this.relay.tran.BLPopAsync(keys, timeout);
}
Как получить доступ к FieldInfo
из IsTransaction
:
private static FieldInfo isTran = typeof(DaemonBase).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance )
.First(x => x.Name == "IsTransaction");
private void DefineMethod(MethodInfo abstractMethod) {
Type essentialReturnType = abstractMethod.ReturnType.GetGenericArguments()[0];
ParameterInfo[] parameters = abstractMethod.GetParameters();
MethodBuilder newMethod = this.typeBuilder.DefineMethod(
abstractMethod.Name,
attributes: MethodAttributes.Public | MethodAttributes.Virtual,
returnType: abstractMethod.ReturnType,
parameterTypes: parameters.Select(par => par.ParameterType).ToArray()
);
this.typeBuilder.DefineMethodOverride(newMethod, abstractMethod);
MethodInfo rediusMethod = typeof(OpsAbs)
.GetMethods(BindingFlags.Public | BindingFlags.Instance)
.Where(x => x.Name == newMethod.Name).First();
ILGenerator ilgen = newMethod.GetILGenerator();
Label falseLabel = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldfld, isTran);
ilgen.Emit(OpCodes.Brfalse, falseLabel); //branching
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldfld, relay);
ilgen.Emit(OpCodes.Ldfld, normalField);
for (int argIndex = 1; argIndex <= parameters.Length; argIndex++) {
ilgen.Emit(OpCodes.Ldarg, argIndex);
}
ilgen.Emit(OpCodes.Callvirt, rediusMethod);
ilgen.Emit(OpCodes.Ret);
ilgen.MarkLabel(falseLabel); //false branch
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldfld, relay);
ilgen.Emit(OpCodes.Ldfld, tranField);
for (int argIndex = 1; argIndex <= parameters.Length; argIndex++) {
ilgen.Emit(OpCodes.Ldarg, argIndex);
}
ilgen.Emit(OpCodes.Callvirt, rediusMethod);
ilgen.Emit(OpCodes.Ret);
}
PS Я знаю, что не показывал много кода, но я пытаюсь понять, почему производный класс (Reflection.Emit
сгенерированный) не может получить доступ к внутреннему полю базового класса?
IsTransaction
является внутренним для DaemonBase
.Почему я не могу получить к нему доступ из производного класса?
PS 2 Я обновил код методом. Я не предоставил реализацию OpsAbs
, так как он используется после того, как яиспользуйте IsTransaction
поле имплозии.