2016-09-06 32 views
1

我想在IL发出一个setter,但是这个setter只能接受非空的对象,如果不是,它必须抛出一个异常。 这是我的Notnull类,它接收il生成器和FieldBuilder,其中setter(如果不为null)必须存储其值。IL发射断开连接的上下文错误

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); 
    } 
} 

我在IL中调用的类utils并抛出我的异常。

class Utils 
    { 
     public void checkIfNull(object obj) 
     { 
      if (obj == null) throw new MyException(); 
     } 
    } 

当我尝试创建我的新类型(具有此IL)时,它会显示Disconnected上下文错误。

+0

你能发布完整的错误?并假设它是一个例外,包括它的堆栈跟踪? – svick

回答

1

您正在使它变得比使用非静态方法更复杂。如果不需要对象引用来调用该方法,则该方法应始终为静态。

这基本上你想现在发射的是:

public string Name 
{ 
    set 
    { 
     Utils u = new Utils(); 
     string s = value; 
     u.checkIfNull(s); 
     _Name = s; 
    } 
} 

其实完全没有必要创建Utils类的实例做了检查。

开始通过使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); 
    } 
} 
+0

非常感谢您的快速回答!我现在看到,实际上我的设置方法很复杂。问题解决了。 –

0

我没有完全理解你想做什么(使用NotNull类和FieldBuilder),但我可以告诉你什么是IL哟你需要你的setter属性(检查null和set字段)。

如果它对你有用,太好了。如果没有,让我知道这个问题,我们会解决它。

首先让我们描述我们想要的。

  1. 创建Utils
  2. 负载value ARG
  3. 呼叫checkIfNull
  4. 负载this
  5. 负载value
  6. 集字段
  7. 惩戒

emit才会是这样的:

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 
+0

无需创建'Utils'类的实例。 'checkIfNull'应该是静态的。看到我的答案。 –

+0

@MrAnderson“不需要”取决于问题所有者。我看到了你的答案,并确信它可以很好。 (很好,你记得在静态时发出'call')。我只是回答他的问题。 –

+0

是的,你说得对。我只是想帮助OP,因为他可能不了解静态方法,因为这将是使用它们的地方。 –

相关问题