您現在的位置是:首頁 > 動作武俠首頁動作武俠

怎樣讓1+1=3?

簡介NET Core應用中針對IHostEnvironment的如下三個擴充套件方法的實現,因為我們的部署環境並沒有按照預設的命名約定(Development、Staging和Production)這樣導致了這三個方法返回錯誤的結果

一加一在什麼情況下等於三

如下所示的是一個。NET程式。我們在這段程式中定義了一個作整數加法運算的Add方法,但是我希望將針對這個方法的呼叫轉移到另一個Add2方法上,為此我定義了一個Override方法。

class Program{ static void Main() { Override(() => Add(default, default), () => Add2(default, default)); Console。WriteLine($“Add(1, 1) == {Add(1, 1)}”); Console。ReadLine(); } public static int Add(int x, int y) => x + y; public static int Add2(int x, int y) => x + y + 1; public static void Override(Expression originalCall, Expression targetCall);}

從如下所示的輸出可以看出:雖然源程式我們呼叫的是Add方法,實際上最終的呼叫被轉移到Add2方法上。

怎樣讓1+1=3?

我們知道透過C#編寫的。NET程式在編譯後會轉化成IL Code,在執行時以及時編譯的方式轉化成機器指令。如果想“篡改”某個方法的實現,要麼在JIT之前改變IL程式碼,要麼直接修改最終的機器指令。Override方法採用的是第二種解決方案,如下所示的該方法的實現,基本的思路就是將將原方法的機器指令修改為JUMP(對應x86二進位制為0xE9)指令實現向目標方法的跳轉。

public static void Override(Expression originalCall, Expression 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 - 1); byte[] instruction = { 0xE9, // JUMP (byte)(offset & 0xFF), (byte)((offset >> 8) & 0xFF), (byte)((offset >> 16) & 0xFF), (byte)((offset >> 24) & 0xFF) }; Marshal。Copy(instruction, 0, sourceAddress, instruction。Length);}

這個方式有時候會很有用,我最近應用的場景是希望篡改。NET Core應用中針對IHostEnvironment的如下三個擴充套件方法的實現,因為我們的部署環境並沒有按照預設的命名約定(Development、Staging和Production)這樣導致了這三個方法返回錯誤的結果。但是IsDevelopment方法的返回結果在。NET Core服務承載系統中很重要,所以不得不篡改它的實現邏輯。

public static class HostEnvironmentEnvExtensions{ public static bool IsDevelopment(this IHostEnvironment hostEnvironment) =>hostEnvironment。IsEnvironment(Environments。Development); public static bool IsProduction(this IHostEnvironment hostEnvironment) =>hostEnvironment。IsEnvironment(Environments。Production); public static bool IsStaging(this IHostEnvironment hostEnvironment) =>hostEnvironment。IsEnvironment(Environments。Staging);}public static class Environments{ public static readonly string Development = “Development”; public static readonly string Production = “Production”; public static readonly string Staging = “Staging”;}

從某種意義上講,這也體現了。NET Core Hosting System在設計上的一個問題,希望在以後的版本中能夠解決這個問題。

作者:蔣金楠

出處:https://www。cnblogs。com/artech/p/11354583。html。

本文版權歸作者和部落格園共有。

Top