我想得到这个:
.property instance class [WorldTool.Core]WorldTool.IInputPort SomePort
{
.get instance class [WorldTool.Core]WorldTool.IInputPort WorldTool.Core.Tests.SomeOperatorInstance::get_SomePort()
}
但我得到这个:
.property class class [WorldTool.Core]WorldTool.IInputPort SomePort
{
.get instance class [WorldTool.Core]WorldTool.IInputPort SomeOperatorInstanceProxy::get_SomePort()
}
为什么我得到的是".property类"而不是".property实例类"?这是我用来生成它的方法:
private void CreateProperty(TypeBuilder typeBuilder, PropertyInfo propertyInfo)
{
var propertyBuilder = typeBuilder.DefineProperty(propertyInfo.Name,
PropertyAttributes.HasDefault,
propertyInfo.PropertyType,
Type.EmptyTypes);
var methodBuilder = typeBuilder.DefineMethod(GET_PREFIX + propertyInfo.Name,
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final,
propertyInfo.PropertyType,
Type.EmptyTypes);
var methodGenerator = methodBuilder.GetILGenerator();
methodGenerator.DeclareLocal(propertyInfo.PropertyType);
methodGenerator.Emit(OpCodes.Nop);
methodGenerator.Emit(OpCodes.Ldarg_0);
methodGenerator.Emit(OpCodes.Ldstr, propertyInfo.Name);
methodGenerator.Emit(OpCodes.Call, typeof(IInputPort).IsAssignableFrom(propertyInfo.PropertyType) ? GetNamedInputPort : GetNamedOutputPort);
methodGenerator.Emit(OpCodes.Stloc_0);
var targetInstruction = methodGenerator.DefineLabel();
methodGenerator.Emit(OpCodes.Br_S, targetInstruction);
methodGenerator.MarkLabel(targetInstruction);
methodGenerator.Emit(OpCodes.Ldloc_0);
methodGenerator.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(methodBuilder);
}
定义属性时需要指定调用约定。
你有:
var propertyBuilder = typeBuilder.DefineProperty(
propertyInfo.Name,
PropertyAttributes.HasDefault,
propertyInfo.PropertyType,
Type.EmptyTypes);
你需要:
var propertyBuilder = typeBuilder.DefineProperty(
propertyInfo.Name,
PropertyAttributes.HasDefault,
CallingConventions.HasThis, // ding ding ding
propertyInfo.PropertyType,
Type.EmptyTypes);
对于任何希望重复我的发现的人,这是我使用的测试代码:
namespace EmitTest
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection.Emit;
using System.Reflection;
public class TestPropertyBuilde
{
TypeBuilder tb;
FieldBuilder countFB;
// The code in this class generates the code in the following comment:
/*
namespace EmitTest
{
public class TestType
{
private int count;
public int TestProperty
{
get
{
return this.count;
}
}
public TestType()
{
this.count = 1;
}
}
}
*/
public void Build()
{
AssemblyName name = new AssemblyName( "GeneratedAssm" );
AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
name,
AssemblyBuilderAccess.RunAndSave,
@"C:UsersantiduhDesktopEmitTest" );
ModuleBuilder mb = assembly.DefineDynamicModule( name.Name, name.Name + ".dll" );
this.tb = mb.DefineType( "EmitTest.TestType", TypeAttributes.Public );
CreateVariable();
CreateConstructor();
CreateProperty( "TestProperty", typeof( int ) );
Type dummy = tb.CreateType();
assembly.Save( "GeneratedAssm.dll" );
}
private void CreateVariable()
{
this.countFB = tb.DefineField( "count", typeof( int ), FieldAttributes.Private );
}
private void CreateConstructor()
{
ConstructorBuilder ctor0 = tb.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
Type.EmptyTypes );
var gen = ctor0.GetILGenerator();
gen.Emit( OpCodes.Ldarg_0 );
gen.Emit( OpCodes.Call, typeof( object ).GetConstructor( Type.EmptyTypes ) );
gen.Emit( OpCodes.Ldarg_0 );
gen.Emit( OpCodes.Ldc_I4_1 );
gen.Emit( OpCodes.Stfld, countFB);
gen.Emit( OpCodes.Ret );
}
private void CreateProperty(string propertyName, Type propType )
{
var propertyBuilder = tb.DefineProperty(
propertyName,
PropertyAttributes.HasDefault,
CallingConventions.HasThis,
propType,
Type.EmptyTypes );
var methodBuilder = tb.DefineMethod(
"get_" + propertyName,
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final,
propType,
Type.EmptyTypes );
var methodGenerator = methodBuilder.GetILGenerator();
methodGenerator.Emit( OpCodes.Ldarg_0 );
methodGenerator.Emit( OpCodes.Ldfld, countFB );
methodGenerator.Emit( OpCodes.Ret );
propertyBuilder.SetGetMethod( methodBuilder );
}
}
}