首页 新闻 会员 周边

Emit动态创建类型调用泛型类静态方法

0
悬赏园豆:140 [已解决问题] 解决于 2014-10-29 20:42
//A:已有的类
public class Creator<T> {
    public static Creator<T> Create() {
        return new Creator<T>();
    }
}

//B:用Emit创建的类
public class Express {
    public Creator<Express> Cache {
        get {
            return Creator<Express>.Create();
        }
    }
}

A是代码中已有的类型,B是希望用Emit动态创建的类型,构建get_Cache方法时会出错,下面是创建的方法:

public static void Create() {
    AssemblyName name = new AssemblyName("Com.DiQiSoft.Demo");
    AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, System.Reflection.Emit.AssemblyBuilderAccess.RunAndSave);
    ModuleBuilder module = assembly.DefineDynamicModule(name.Name, name.Name + ".dll");
    TypeBuilder typeOfExpress = module.DefineType("Express", TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit);
    typeOfExpress.SetParent(typeof(object));
    var creator = typeof(Creator<>);
    var typeOfCreator = creator.MakeGenericType(typeOfExpress);
    var getMethod = typeOfExpress.DefineMethod("get_New", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName, typeOfCreator, Type.EmptyTypes);
    var property = typeOfExpress.DefineProperty("New", PropertyAttributes.HasDefault, typeOfCreator, Type.EmptyTypes);
    var generator = getMethod.GetILGenerator();
    var createMethod = typeOfCreator.GetMethod("Create");
    var local = generator.DeclareLocal(typeOfCreator);
    generator.Emit(OpCodes.Nop);
    generator.Emit(OpCodes.Call, createMethod);
    generator.Emit(OpCodes.Stloc_0);
    var lb = generator.DefineLabel();
    generator.Emit(OpCodes.Br_S, lb);
    generator.MarkLabel(lb);
    generator.Emit(OpCodes.Ldloc_0);
    generator.Emit(OpCodes.Ret);
    property.SetGetMethod(getMethod);
    typeOfExpress.CreateType();
    assembly.Save(name.Name + ".dll");
}


上面的代码在运行到:

var createMethod = typeOfCreator.GetMethod("Create");

这一行时会提示错误:不支持所指定的方法。

问题补充:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;

namespace Demo {
    class Program {

        static void Main(string[] args) {
            Create();
        }

        public static void Create() {
            AssemblyName name = new AssemblyName("Com.DiQiSoft.Demo");
            AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, System.Reflection.Emit.AssemblyBuilderAccess.RunAndSave);
            ModuleBuilder module = assembly.DefineDynamicModule(name.Name, name.Name + ".dll");
            TypeBuilder typeOfExpress = module.DefineType("Express", TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit);
            typeOfExpress.SetParent(typeof(object));
            var creator = typeof(Creator<>);
            var typeOfCreator = creator.MakeGenericType(typeOfExpress);
            var getMethod = typeOfExpress.DefineMethod("get_New", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName, typeOfCreator, Type.EmptyTypes);
            var property = typeOfExpress.DefineProperty("New", PropertyAttributes.HasDefault, typeOfCreator, Type.EmptyTypes);
            var generator = getMethod.GetILGenerator();
            var createMethod = typeOfCreator.GetMethod("Create");
            var local = generator.DeclareLocal(typeOfCreator);
            generator.Emit(OpCodes.Nop);
            generator.Emit(OpCodes.Call, createMethod);
            generator.Emit(OpCodes.Stloc_0);
            var lb = generator.DefineLabel();
            generator.Emit(OpCodes.Br_S, lb);
            generator.MarkLabel(lb);
            generator.Emit(OpCodes.Ldloc_0);
            generator.Emit(OpCodes.Ret);
            property.SetGetMethod(getMethod);
            typeOfExpress.CreateType();
            assembly.Save(name.Name + ".dll");
        }
    }

    public class Creator<T> {
        public static Creator<T> Create() {
            return new Creator<T>();
        }
    }
}

上面是完整的测试代码,新建一个控制台程序复制进去就可以运行了。

I,Robot的主页 I,Robot | 大侠五级 | 园豆:9783
提问于:2014-10-29 09:08
< >
分享
最佳答案
1

So hard for remember,需要翻文档...

收获园豆:110
幻天芒 | 高人七级 |园豆:37175 | 2014-10-29 09:33

折腾了一个晚上没找到方法,静候佳音,谢谢

I,Robot | 园豆:9783 (大侠五级) | 2014-10-29 09:39

@DiQiSoft.Com:

 var createMethod = TypeBuilder.GetMethod(typeOfCreator, creator.GetMethod("Create"));

 

生成的代码为:

public class Express
{
    public Creator<Express> New
    {
        get
        {
            return Creator<Express>.Create();
        }
    }
}

 

幻天芒 | 园豆:37175 (高人七级) | 2014-10-29 12:35

@幻天芒: 搞定,万分感谢

I,Robot | 园豆:9783 (大侠五级) | 2014-10-29 20:40

@DiQiSoft.Com: 共同进步,我也是在StackOverflow上找到的方案,然后测试成功了。

幻天芒 | 园豆:37175 (高人七级) | 2014-10-30 08:57
其他回答(3)
0

以前用过、都忘记了。帮顶

收获园豆:10
小二炒豆芽菜 | 园豆:418 (菜鸟二级) | 2014-10-29 09:26

谢谢

支持(0) 反对(0) I,Robot | 园豆:9783 (大侠五级) | 2014-10-29 09:32
0

查看一下typeOfCreator都有哪些方法。

帮顶!

收获园豆:10
CaiYongji | 园豆:1267 (小虾三级) | 2014-10-29 09:35

typeOfCreator的类型没记错的话好像是TypeBuilderInstantiation

支持(0) 反对(0) I,Robot | 园豆:9783 (大侠五级) | 2014-10-29 09:40
0

帮顶!

 
收获园豆:10
迅捷网络[来送福利] | 园豆:576 (小虾三级) | 2014-10-29 09:37

谢谢

支持(0) 反对(0) I,Robot | 园豆:9783 (大侠五级) | 2014-10-29 09:40
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册