ILGenerator 属性不是实例



我想得到这个:

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

}

相关内容

  • 没有找到相关文章

最新更新