在运行时用新创建的类型替换现有的 class 定义
Replace existing class definition at runtime with newly created type
德莫雷波:
https://github.com/gabbersepp/csharp-dynamic-replace-class
使用方法:
- 结帐
- 编译
- 从 console/bin/Debug
中删除 TestLib.dll & TestLib.pdb
- 通过cmd
执行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
德莫雷波:
https://github.com/gabbersepp/csharp-dynamic-replace-class
使用方法:
- 结帐
- 编译
- 从 console/bin/Debug 中删除 TestLib.dll & TestLib.pdb
- 通过cmd 执行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