2011-11-15 2 views
1

Reflection.Emit-Namespace를 사용하여 런타임시 .NET 유형을 디자인하고 있습니다..NET에서 Reflection.Emit을 사용하여 하드 코딩 된 기존 메서드 호출

Dim AssemblyBuilder As AssemblyBuilder = Nothing 
Dim ModuleBuilder As ModuleBuilder = Nothing 
Dim TypeBuilder As TypeBuilder = Nothing 

Dim MethodBuilder As MethodBuilder 
Dim ReturnType As Type = Nothing 

AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(New AssemblyName("DynamicAssembly"), AssemblyBuilderAccess.RunAndSave) 

ModuleBuilder = AssemblyBuilder.DefineDynamicModule("DynamicAsssembly", "DynamicAssembly.dll") 
TypeBuilder = ModuleBuilder.DefineType("DynamicType") 

MethodBuilder = TypeBuilder.DefineMethod("Do", MethodAttributes.Public, Nothing, Nothing) 

위 작품 : 현재, 나는 생성 클래스에 이미 존재하는 메소드를 호출하는 방법을 생성하려고 해요.

MethodBuilder.GetILGenerator.EmitCall(OpCodes.Call, Me.GetType.GetMethod("DisplayString"), Nothing) 
MethodBuilder.GetILGenerator.Emit(OpCodes.Ret) 

ReturnType = TypeBuilder.CreateType() 
Activator.CreateInstance(ReturnType) 

일반적으로 다음과 같이하고 싶습니다. 실행중인 클래스 자체에있는 메소드를 호출합니다. 그러나 다음을 호출 할 때 예외가 발생합니다.

ReturnType.GetMethod("Do").Invoke(Activator.CreateInstance(ReturnType), Nothing) 

내부 예외는 다음과 같습니다. InvalidProgramException, "공용 언어 런타임에서 잘못된 프로그램을 발견했습니다."

예를 들어 전화를 발신 한 위의 행을 바꾸면

MethodBuilder.GetILGenerator.Emit(OpCodes.Ldstr, "test") 
MethodBuilder.GetILGenerator.EmitCall(OpCodes.Call, GetType(System.Windows.Forms.MessageBox).GetMethod("Show", {GetType(String)}), {GetType(String)}) 
MethodBuilder.GetILGenerator.Emit(OpCodes.Pop) 

잘 작동합니다.

실행중인 어셈블리 유형과 해당 멤버에 액세스 할 수 없기 때문에 문제가 발생한다고 생각합니다. 그렇지만 실행하기 위해 변경할 수있는 항목은 무엇입니까?

감사

모모

+0

'DisplayString' 메소드의 서명은 무엇입니까? – svick

답변

0

DisplayString는 정적 메소드 (MessageBox.Show은)인가?)이 도움이

dim fieldBuilder as FieldBuilder = typeBuilder.DefineField(
       "o", Me.GetType(), 
       FieldAttributes.InitOnly | FieldAttributes.Private); 


dim constructor as ConstructorBuilder = typeBuilder.DefineConstructor(
       MethodAttributes.Public | 
       MethodAttributes.HideBySig | 
       MethodAttributes.SpecialName | 
       MethodAttributes.RTSpecialName, 
       CallingConventions.Standard, new[] { Me.GetType() }); 

//Make tho CTOR for the dynamic type, it needs to take an argument of the 
//instance to call the method on (in this case it will be Me) 

dim il as ILGenerator = constructor.GetILGenerator(); 

il.Emit(OpCodes.Ldarg_0); 

il.Emit(OpCodes.Call, baseCtor); 

il.Emit(OpCodes.Ldarg_0); 
il.Emit(OpCodes.Ldarg_1); 
il.Emit(OpCodes.Stfld, fieldBuilder); 

il.Emit(OpCodes.Ret); 

// Make the method 
il = methodBuilder.GetILGenerator(); 

il.Emit(OpCodes.Ldarg, 0); 
il.Emit(OpCodes.Ldfld, fieldBuilder); 
il.Emit(OpCodes.Ldstr, 'test'); 

il.Emit(OpCodes.Callvirt, Me.GetType.GetMethod ... 
il.Emit(OpCodes.Ret); 

희망을,

당신은 내 mangeled VB, 그 있었다 꽤을 제공하기위한

하시기 바랍니다에 메소드를 호출 인스턴스를 필요로하기 위하여려고하고있다 그렇지 않으면.

무엇을 방출해야 하는지를 배우는 가장 좋은 방법 중 하나는 정상적으로 클래스를 쓰고 그 다음에 IL DASM을 사용하면 그 코드에서 OpCodes를 복사 할 수 있습니다.

+0

많은 감사합니다! 나는 수업에서 하나의 인스턴스를 가져와야한다는 사실을 잊어 버렸다. 방금 정적 (공유) 방법으로 만들었고 효과가있었습니다. 좀 더 시간이 있으면 인스턴스 메서드를 호출하려고합니다. ILDASM 팁을 가져 주셔서 감사합니다. 나는 이미 그것을했지만, 나는 항상 그곳에서 일어나는 일을 이해하기가 어렵다. – user1046555

관련 문제