在运行时用新创建的类型替换现有的 class 定义

Replace existing class definition at runtime with newly created type

德莫雷波:

https://github.com/gabbersepp/csharp-dynamic-replace-class

使用方法:

  1. 结帐
  2. 编译
  3. 从 console/bin/Debug
  4. 中删除 TestLib.dll & TestLib.pdb
  5. 通过cmd
  6. 执行console.exe

先读:

我想在工作中实现一些目标,我认为这将是最好的解决方案。所以请不要讨论我是否可以用其他方式解决这个问题。如果我想讨论这个,我会创建一个新的 SO post.

给定:

库中的一个class:

namespace Test.TestLib
{
    public class Class1
    {
    }
}

第二个 class 创建它的一个实例:

namespace console
{
    public class AnotherClass
    {
        public void Create()
        {
            new Class1();
        }
    }
}

还有一个调用 create 的控制台应用程序:

    static void Main(string[] args)
    {
        //...
        new AnotherClass().Create();
    }

请记住只有 Class1 在额外的库中。另外两个class也是一样的

我想做什么:

在运行时替换类型 Class1

        AssemblyName dynamicAssemblyName = new AssemblyName("TestLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
        dynamicAssembly =
            AssemblyBuilder.DefineDynamicAssembly(dynamicAssemblyName, AssemblyBuilderAccess.Run);
        var dynamicModule = dynamicAssembly.DefineDynamicModule("TestLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
        var modelType = dynamicModule.DefineType("Test.TestLib.Class1", TypeAttributes.Class).CreateType();

这行得通。如果我使用 Activator:Activator.CreateInstance(modelType); 我会得到一个这种类型的新实例。

但是:

当到达new Class1行时,抛出异常:

Unbehandelte Ausnahme: System.MethodAccessException: Fehler beim Versuch der Methode "console.AnotherClass.Create()", auf Methode "Test.TestLib.Class1..ctor()" zuzugreifen. bei console.AnotherClass.Create()

类似于:

Unhandled exception: System.MethodAccessException: An error occurred while trying to access the method "console.AnotherClass.Create ()" method "Test.TestLib.Class1..ctor ()".     at console.AnotherClass.Create ()

问题:

这可能吗?

旁注: 需要从 /debug 文件夹中删除 TestLib 文件,否则不会引发 AsemblyResolve 事件(请参阅 repo 以获取完整示例)

您新创建的类型的构造函数不是 public,因此 MethodAccessAcception

您可以在 TypeBuilder 实例上使用以下调用创建一个 public 默认构造函数:

var modelTypeBuilder = dynamicModule.DefineType("Test.TestLib.Class1", TypeAttributes.Class);
modelTypeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
var modelType = modelTypeBuilder.CreateType();

否则您可以使用 modelTypeBuilder.DefineConstructor() 设置更多可能的选项。

在DefineType中添加TypeAttributes.Public,会执行成功
检查这个:https://github.com/aIjundi/csharp-dynamic-replace-class