加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

怎样让1+1=3?

发布时间:2020-12-16 09:08:06 所属栏目:asp.Net 来源:网络整理
导读:如下所示的是一个.NET程序。我们在这段程序中定义了一个作整数加法运算的Add方法,但是我希望将针对这个方法的调用转移到另一个Add2方法上,为此我定义了一个Override方法。 class Program{ static void Main() { Override(() = Add( default , default ),()

如下所示的是一个.NET程序。我们在这段程序中定义了一个作整数加法运算的Add方法,但是我希望将针对这个方法的调用转移到另一个Add2方法上,为此我定义了一个Override方法。

class Program
{
    static void Main()
    {
        Override(() => Add(default,default),() => Add2(default));
        Console.WriteLine($"Add(1,1) == {Add(1,1)}");
        Console.ReadLine();
    }

    public int Add(int x,1)">int y) => x + y;
    int Add2(int y) => x + y + 1;
    void Override(Expression<Action> originalCall,Expression<Action> targetCall);
}

从如下所示的输出可以看出:虽然源程序我们调用的是Add方法,实际上最终的调用被转移到Add2方法上。

我们知道通过C#编写的.NET程序在编译后会转化成IL Code,在运行时以及时编译的方式转化成机器指令。如果想“篡改”某个方法的实现,要么在JIT之前改变IL代码,要么直接修改最终的机器指令。Override方法采用的是第二种解决方案,如下所示的该方法的实现,基本的思路就是将将原方法的机器指令修改为JUMP(对应x86二进制为0xE9)指令实现向目标方法的跳转。

targetCall) { var originalMethod = ((MethodCallExpression)originalCall.Body).Method; var targetMethod = ((MethodCallExpression)targetCall.Body).Method; RuntimeHelpers.PrepareMethod(originalMethod.MethodHandle); RuntimeHelpers.PrepareMethod(targetMethod.MethodHandle); var sourceAddress = originalMethod.MethodHandle.GetFunctionPointer(); var targetAddress = (long)targetMethod.MethodHandle.GetFunctionPointer(); int offset = (int)(targetAddress - (long)sourceAddress - 4 - ); byte[] instruction = { 0xE9,1)">// JUMP (byte)(offset & 0xFF),(byte)((offset >> 8) & 16) & 24) & ) }; Marshal.Copy(instruction,0,sourceAddress,instruction.Length); }

这个方式有时候会很有用,我最近应用的场景是希望篡改.NET Core应用中针对IHostEnvironment的如下三个扩展方法的实现,因为我们的部署环境并没有按照默认的命名约定(Development、Staging和Production)这样导致了这三个方法返回错误的结果。但是IsDevelopment方法的返回结果在.NET Core服务承载系统中很重要,所以不得不篡改它的实现逻辑。

HostEnvironmentEnvExtensions { bool IsDevelopment(this IHostEnvironment hostEnvironment) =>hostEnvironment.IsEnvironment(Environments.Development); bool IsProduction(hostEnvironment.IsEnvironment(Environments.Production); bool IsStaging(hostEnvironment.IsEnvironment(Environments.Staging); } Environments { readonly string Development = Developmentstring Production = Productionstring Staging = Staging; }

从某种意义上讲,这也体现了.NET Core Hosting System在设计上的一个问题,希望在以后的版本中能够解决这个问题。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读