IL 发出断开连接的上下文错误
IL Emit Disconnected Context Error
我试图在 IL 中发出一个 setter,但是这个 setter 必须只接受非空的对象,如果不是,它必须抛出异常。
这是我的 class Notnull,它接收一个 il Generator 和一个 FieldBuilder,其中 setter(如果不是 null)必须存储它的值。
public class NonNull
{
public void CreateIL(ILGenerator il, FieldBuilder field)
{
il.Emit(OpCodes.Ldarg_0); // Push "this" on the stack
il.Emit(OpCodes.Newobj, typeof(Utils).GetConstructor(new Type[] { }));
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Stloc_2);
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Ldloc_1); // Push "value" on the stack
il.Emit(OpCodes.Callvirt,typeof(Utils).GetMethod("checkIfNull"));
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Stfld, field); // Set the field "_Name" to "value"
il.Emit(OpCodes.Ret);
}
}
Class 我在 IL 中调用并抛出异常的实用程序。
class Utils
{
public void checkIfNull(object obj)
{
if (obj == null) throw new MyException();
}
}
当我尝试创建我的新类型(具有此 IL)时,它显示断开连接的上下文错误。
您使用非静态方法使它变得比需要的复杂得多。如果不需要对象引用来调用该方法,则该方法应始终是静态的。
这基本上就是您现在要发出的内容:
public string Name
{
set
{
Utils u = new Utils();
string s = value;
u.checkIfNull(s);
_Name = s;
}
}
绝对不需要创建 Utils
class 的实例来进行检查。
首先将 checkIfNull()
设为静态:
static class Utils
{
public static void checkIfNull(object obj)
{
if (obj == null) throw new MyException();
}
}
这是您应该尝试发出的内容:
public string Name
{
set
{
Utils.checkIfNull(value);
_Name = value;
}
}
方法如下:
public class NonNull
{
public static void CreateIL(ILGenerator il, FieldBuilder field)
{
il.Emit(OpCodes.Ldarg_1); // Push "value" on the stack
il.Emit(OpCodes.Call, typeof(Utils).GetMethod("checkIfNull"));
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Stfld, field); // Set the field "_Name" to "value"
il.Emit(OpCodes.Ret);
}
}
我不明白你到底想做什么(使用 NotNull class 和 FieldBuilder),但我可以告诉你你的 setter [=46= 需要什么 IL ](检查空值并设置字段)。
如果它对你有用,那就太好了。如果没有,请告诉我问题,我们会解决它。
首先让我们描述一下我们想要什么。
- 创建
Utils
class
- 加载
value
参数
- 致电
checkIfNull
- 加载
this
- 加载
value
- 设置字段
- 退
发射将是这样的:
il.Emit(OpCodes.Newobj, typeof(Utils).GetConstructor(new Type[] { }));
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Callvirt,typeof(Utils).GetMethod("checkIfNull"));
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Stfld, field);
il.Emit(OpCodes.Ret);
结果需要如下所示:
newobj instance void MyApplication.Utils::.ctor() //create `Utils` object
ldarg.1 //load `value`
callvirt instance void
MyApplication.Utils::checkIfNull(object) //call checkForNull
ldarg.0 //load `this`
ldarg.1 //load `value`
stfld int32 MyApplication.Program::_field //store `value` in `_field`
ret
我试图在 IL 中发出一个 setter,但是这个 setter 必须只接受非空的对象,如果不是,它必须抛出异常。 这是我的 class Notnull,它接收一个 il Generator 和一个 FieldBuilder,其中 setter(如果不是 null)必须存储它的值。
public class NonNull
{
public void CreateIL(ILGenerator il, FieldBuilder field)
{
il.Emit(OpCodes.Ldarg_0); // Push "this" on the stack
il.Emit(OpCodes.Newobj, typeof(Utils).GetConstructor(new Type[] { }));
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Stloc_2);
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Ldloc_1); // Push "value" on the stack
il.Emit(OpCodes.Callvirt,typeof(Utils).GetMethod("checkIfNull"));
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Stfld, field); // Set the field "_Name" to "value"
il.Emit(OpCodes.Ret);
}
}
Class 我在 IL 中调用并抛出异常的实用程序。
class Utils
{
public void checkIfNull(object obj)
{
if (obj == null) throw new MyException();
}
}
当我尝试创建我的新类型(具有此 IL)时,它显示断开连接的上下文错误。
您使用非静态方法使它变得比需要的复杂得多。如果不需要对象引用来调用该方法,则该方法应始终是静态的。
这基本上就是您现在要发出的内容:
public string Name
{
set
{
Utils u = new Utils();
string s = value;
u.checkIfNull(s);
_Name = s;
}
}
绝对不需要创建 Utils
class 的实例来进行检查。
首先将 checkIfNull()
设为静态:
static class Utils
{
public static void checkIfNull(object obj)
{
if (obj == null) throw new MyException();
}
}
这是您应该尝试发出的内容:
public string Name
{
set
{
Utils.checkIfNull(value);
_Name = value;
}
}
方法如下:
public class NonNull
{
public static void CreateIL(ILGenerator il, FieldBuilder field)
{
il.Emit(OpCodes.Ldarg_1); // Push "value" on the stack
il.Emit(OpCodes.Call, typeof(Utils).GetMethod("checkIfNull"));
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Stfld, field); // Set the field "_Name" to "value"
il.Emit(OpCodes.Ret);
}
}
我不明白你到底想做什么(使用 NotNull class 和 FieldBuilder),但我可以告诉你你的 setter [=46= 需要什么 IL ](检查空值并设置字段)。
如果它对你有用,那就太好了。如果没有,请告诉我问题,我们会解决它。
首先让我们描述一下我们想要什么。
- 创建
Utils
class - 加载
value
参数 - 致电
checkIfNull
- 加载
this
- 加载
value
- 设置字段
- 退
发射将是这样的:
il.Emit(OpCodes.Newobj, typeof(Utils).GetConstructor(new Type[] { }));
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Callvirt,typeof(Utils).GetMethod("checkIfNull"));
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Stfld, field);
il.Emit(OpCodes.Ret);
结果需要如下所示:
newobj instance void MyApplication.Utils::.ctor() //create `Utils` object
ldarg.1 //load `value`
callvirt instance void
MyApplication.Utils::checkIfNull(object) //call checkForNull
ldarg.0 //load `this`
ldarg.1 //load `value`
stfld int32 MyApplication.Program::_field //store `value` in `_field`
ret