【问题标题】:Replacing a .NET type at runtime在运行时替换 .NET 类型
【发布时间】:2009-12-07 20:10:32
【问题描述】:

我有一个 .NET 程序集,它在编译时定义了一个类型 T,并且我已经实例化了一个对象 my_t 作为这种类型的一个实例。

我想知道是否可以在 .NET 中使用运行时编译器服务重新编译这个类,然后将新的类定义加载到当前正在执行的程序集中,所以当我从 my_t 调用方法时,它们将使用新代码。

我不会更改任何方法的签名,只是更改方法体。

任何 .NET 专家都知道这是否可行?提前感谢您的帮助!

【问题讨论】:

  • 我永远不会做这样的事情。为什么不使用继承?
  • 是的 - 用例是什么?为什么不使用插件架构?编译你的动态插件并加载它,显然传递你的插件接口。
  • 我同意前面的发言者。这样,当我在一个类中调用一个方法时,我无法确定它会做什么即使我可以访问代码。听起来很混乱,这就是 OO 所要防止的。你想要的可能可以通过依赖注入模式来实现
  • 虽然上述 cmets 确实专注于最佳实践(我必须同意),但您应该注意,最佳实践并不总是一种选择,奇怪的螺旋球黑客是唯一的方法一些工作(即,也许他不控制程序集,或者调用他想要替换的方法的类)。

标签: .net


【解决方案1】:

可以交换方法实现,但如果可以选择运行不安全的代码,并且您要交换的方法尚未经过 NGen'd 或“Zapped” .

基本过程在概念上非常简单:您将方法的 JIT 代码所在的内存地址与另一个方法的 JIT 代码的内存地址交换(您也可以强制 CLR 在首先,避免奇怪的先决条件问题)。

CodeProject.com 上有一个很棒的概念验证项目: http://www.codeproject.com/Articles/37549/CLR-Injection-Runtime-Method-Replacer

去看看吧!

【讨论】:

  • 最后,一个问题的实际答案。谢谢!
【解决方案2】:

我不确定这是否可能,但如果是的话,这听起来像是一个非常混乱的解决方案。

使用插件架构,因此您可以动态编译生成的插件,从插件接口继承,然后简单地从新创建的程序集中加载该类型并将其注入到插件容器中。

【讨论】:

    【解决方案3】:

    您可以使用城堡动态代理来创建您的班级的代理。代理是一种新类型,可以让您注入新的实现,但您要注入的任何东西都必须声明为虚拟。

    【讨论】:

    • 有趣——我猜你说的是castleproject.org/dynamicproxy/index.html——你用过这个吗?如果您碰巧知道,性能如何受到影响?谢谢!
    • 我在我的一个项目中使用过它,性能影响应该稳定,因为它实际上会生成代码并将其编译成适合您类型的程序集。
    【解决方案4】:

    .NET 对象不能在运行时更改类型;这是 CLR 中的一个基本假设。

    一些建议:

    1. 编写T 的代码以将呼叫转发到适当的类型。如果您愿意,它可以转发到在运行时编译的类型。
    2. 使用某种面向方面或动态代理框架来为您自动化 (1)
    3. 如果这种转发方式不合适,我相信有一个可供本机使用的 .NET 分析 API 可以让您拦截 JIT 进程。我所知道的是,像 NCover 这样的工具能够以这种方式注入自己的机器代码。

    【讨论】:

    • 我认为您的建议 #1 很有希望 - 我现在有一个原型正在工作。一个问题是调用 my_t.GetType().GetMethod("my_method_name") 与直接调用 my_t.my_method_name 相比是否会对性能造成重大影响。有什么想法吗?
    • 这是一个可怕的性能打击。看看 ashish.s 的 Castle Dynamic Proxy 建议。
    【解决方案5】:

    扩展我的评论:

    public class Base
    {
        public virtual void Method()
        {
    
        }
    }
    
    public class Sub : Base
    {
        public override void Method()
        {
    
        }
    }
    
    public void DoStuff<T>() where T : Base, new()
    {
        var instance = new T();
        instance.Method();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多