【问题标题】:Emit method to override non-virtuals用于覆盖非虚拟的发射方法
【发布时间】:2014-06-09 06:13:04
【问题描述】:

所以我的程序集中有一个简单的类:

public class MyCalculator
  {
    public int Sum(params int[] nums)
    {
      Console.WriteLine("Summing");
      return nums.Sum();
    }
  }

首先要知道的是 Sum 方法不是虚拟的。我不想要这个限制。
我想“覆盖”Sum 方法以在运行时注入一些代码。 (就像任何动态代理框架一样。/例如:Castle/)
我创建了一个虚拟方法(只是相关部分):

MethodBuilder sumBuilder = myCalculatorProxyType.DefineMethod(myCalculatorSum.Name,
        MethodAttributes.Public |
        MethodAttributes.ReuseSlot |
        MethodAttributes.HideBySig |
        MethodAttributes.SpecialName |
        MethodAttributes.Virtual |
        MethodAttributes.Final,
        CallingConventions.Standard, 
        myCalculatorSum.ReturnType, 
        myCalculatorSum.GetParameters().Select(pi => pi.ParameterType).ToArray());

最后我尝试“覆盖”它:

myCalculatorProxyType.DefineMethodOverride(sumBuilder,myCalculatorSum);

我玩了三个可能的选项:

  • MethodAttributes
  • 召唤约定
  • 还有DefineMethodOverride方法

我的概念:让方法Public明显和HideBySig。在 vtable 中附加 ReuseSlot 并使用 ExplicitThis 调用它。
知道如何实现这一目标吗?还是需要一些更讨厌的东西?
我知道外面有框架,但我想了解这个的概念。

【问题讨论】:

  • 您不能覆盖非虚拟。 AFAIK,Castle 也做不到。像 PostSharp 这样的东西可以,但它通过实际更改编译的程序集来工作,而不是创建新的派生类型。
  • 可能重复link
  • @svick:你是对的。继承代理仅支持城堡中的虚拟成员。但我的基本想法是 IL 比 C# 了解更多。 (例如没有类的主要方法:))
  • @SargisKoshkaryan:链接的帖子是关于 C# 而不是 IL

标签: .net dynamic overriding cil reflection.emit


【解决方案1】:

如果您特别想覆盖该方法,那么正如 svick 在评论中所说,您不走运。原因是如果该方法在 IL 中没有被标记为 virtual(这与 C# 中的 virtual 有点不同),那么它将不会在虚拟方法表中获得一个槽,因此子类无法覆盖它。有时 C# 会在 IL 中将非虚拟方法编译为 virtual 和 final,但如果您尝试覆盖 final 方法,则验证失败会带来安全风险。

如果您尝试替换方法的行为(例如在模拟对象时),那么仍有一些潜在的选择。

远程处理

如果对象恰好继承自 MarshalByRefObject,那么您可以使用远程处理系统来模拟对象。本质上,告诉 CLR 该对象存在于其他地方,并且您将代表它编组消息。这种方法将允许您模拟非虚拟实例方法,只要它们定义在从 MarshalByRefObject 继承的对象上并从对象外部调用。

分析

分析 API 允许在 jit 时间进行检测。这允许您更改任何托管方法的行为,包括框架中的静态方法。但是,这里的灵活性是有代价的,它需要付出更多的努力来实现,并且需要使用特定的分析器来运行该过程 - 如果您确实需要分析您的代码,这是一个严重的问题。

我已经在一个或另一个模拟库中看到了这两种方法,我认为这两种方法都不适合生产代码。

【讨论】:

    猜你喜欢
    • 2012-06-19
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2011-08-16
    • 2014-03-18
    • 1970-01-01
    • 2012-10-26
    相关资源
    最近更新 更多