2016-09-06 5 views
1

IL에서 방출자를 만들려고하지만이 설정자는 null이 아닌 개체 만 받아 들여야합니다. 그렇지 않은 경우 예외를 throw해야합니다. 이것은 il Generator와 setter (null이 아닌 경우)가 값을 저장해야하는 FieldBuilder를받는 My class Notnull입니다.일리노이 연결 끊김 컨텍스트 오류를 ​​내 보냅니다

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에서 호출하여 예외를 throw하는 클래스 utils입니다.

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

이 IL이있는 새 유형을 만들려고하면 연결이 끊어진 컨텍스트 오류가 발생합니다.

+0

당신이 전체 오류를 게시 할 수 있을까요? 스택 추적을 포함하여 예외라고 가정합니다. – svick

답변

1

정적이 아닌 방법을 사용하면 필요 이상으로 복잡해지고 있습니다. 메서드 참조를 호출하기 위해 객체 참조가 필요하지 않은 경우 메서드는 항상 정적이어야합니다.

이것은 본질적으로 지금 방출하려고하는 것입니다 : 검사를 할 Utils 클래스의 인스턴스를 만들 필요는 절대적으로

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

없습니다.

시작 checkIfNull() 정적함으로써 :

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

이 무엇을 당신이 방출하는 것을 시도해야한다 :

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

내가 정확히 이해하지 못했다 : 여기

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

을 그리고하는 방법 당신이하고 싶은 일 (NotNull 클래스와 FieldBuilder로),하지만 IL을 어떻게 보여줄 수 있습니까? setter 속성이 필요합니다 (null을 확인하고 필드를 설정하십시오).

효과가 있다면 잘됩니다. 그리고 그렇지 않다면, 문제를 알려주고 해결해 드리겠습니다.

먼저 원하는 것을 설명해주십시오.

  1. 만들기 Utils 클래스
  2. 로드 value 인수
  3. 전화 checkIfNull
  4. 로드 this
  5. 로드 value
  6. 세트 필드
  7. 징벌

개의 발광은 다음과 같이 될 것입니다 :

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 "필요 없음"은 질문 소유자에 따라 다릅니다. 나는 당신의 대답을 보았고 그것도 괜찮을 것이라고 확신합니다. (정적 일 때 '호출'을내는 것을 기억하십시오.) 나는 그가 묻는 것에 대답한다. –

+0

네, 맞습니다. 나는 그가 정적 인 방법을 이해하지 못하기 때문에 OP를 돕기 위해 노력하고있다. –

관련 문제