是否可以在c#中为现有模块添加类型?

时间:2014-11-11 15:32:09

标签: c# .net entity-framework reflection entity-framework-6

我有一种情况需要动态地向我的应用程序添加类型。 基本上,正在发生的是我们想要使用EF6,但仍然对数据库运行完全动态查询并返回键/值对的字典。 (遗留代码,不要问)

我可以通过调用context.Database.SqlQuery并传递动态加载的类型来实现这一点,我会动态创建。

我正在使用我在网上找到的这种方法。

private static TypeBuilder CreateTypeBuilder(
    string assemblyName, string moduleName, string typeName)
{

    TypeBuilder typeBuilder = AppDomain.CurrentDomain
        .DefineDynamicAssembly(new AssemblyName(assemblyName), AssemblyBuilderAccess.Run)
        .DefineDynamicModule(moduleName)
        .DefineType(typeName, TypeAttributes.Public);
    typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
    return typeBuilder;
}

哪个很好用,但每次我添加一个新类型(可能经常)它会加载一个新的动态程序集。这可能导致数百个仅使用一次的程序集。

我可以使用以下语句来下拉动态程序集:

var loadedAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(ex => ex.GetName().Name == assemblyName);

我也可以使用以下方法获取动态模块:

var loadedModule = loadedAssembly.GetModules().FirstOrDefault(ex => ex.ScopeName == moduleName);

但就我而言,我无法在此之后添加任何类型。

我是在咆哮错误的树吗?

1 个答案:

答案 0 :(得分:3)

关键部分是这一行:

.DefineDynamicAssembly(new AssemblyName(assemblyName), AssemblyBuilderAccess.Run)
.DefineDynamicModule(moduleName)

该方法返回动态程序集和模块的实例。每次需要新类型时,不要调用DefineDynamicAssemblyDefineDynamicModule,而是创建动态程序集和模块一次,然后在模块上为所需的每种类型调用DefineType。也许是这样的:

internal static class DyanamicTypeBuilder
{
    private static readonly AssemblyBuilder _assembly;
    private static readonly ModuleBuilder _module;
    private static readonly object _syncBlk = new object();

    static DyanamicTypeBuilder()
    {
        _assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("MyDyanmicAssembly"), AssemblyBuilderAccess.Run);
        _module = _assembly.DefineDynamicModule("MyDynamicModule");
    }

    private static TypeBuilder CreateTypeBuilder(string typeName)
    {
        lock (_syncBlk)
        {
            var typeBuilder = _module.DefineType(typeName, TypeAttributes.Public);
            typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
            return typeBuilder;
        }
    }
}