【问题标题】:Replace existing class definition at runtime with newly created type在运行时用新创建的类型替换现有的类定义
【发布时间】:2019-11-18 05:47:52
【问题描述】:

Demorepo

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

如何使用

  1. 结帐
  2. 编译
  3. 从控制台/bin/Debug 中删除 TestLib.dll 和 TestLib.pdb
  4. 通过cmd执行console.exe

先阅读

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

鉴于

库中的类:

namespace Test.TestLib
{
    public class Class1
    {
    }
}

还有一个创建它的实例的第二个类:

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

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

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

请记住,只有Class1 在额外的库中。其他两个类在同一个。

我想做的事

在运行时替换类型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。北 console.AnotherClass.Create()

类似

未处理的异常:System.MethodAccessException:发生错误 在尝试访问方法“console.AnotherClass.Create()”时 方法“Test.TestLib.Class1..ctor ()”。 在console.AnotherClass.Create()

问题

这可能吗?

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

【问题讨论】:

标签: c# .net reflection runtime .net-4.6.1


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您新创建的 Type 的构造函数不是公开的,因此是 MethodAccessAcception

    您可以在 TypeBuilder 实例上使用以下调用来创建公共默认构造函数:

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

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

    【讨论】:

    • 嗨,我只需要像 Sohaib 提到的那样公开整个类型。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-13
    • 1970-01-01
    • 1970-01-01
    • 2011-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多