2016-04-07 89 views
0

一般的原因,我想這樣做是:是否有可能獲得方法內的調用實例?

class MovieApiController : ApiController 
{ 
    public string CurrentUser {get;set;} 

    // ... 

    public string Index() 
    { 
     return Resources.GetText("Color"); 
    } 
} 


class Resources 
{ 
    static string GetText(string id) 
    { 
     var caller = ??? as MovieApiController; 
     if (caller && caller.CurrentUser == "Bob") 
     { 
      return "Red"; 
     } 
     else 
     { 
      return "Blue"; 
     } 
    } 
} 

我不需要這是100%可靠。看來這個調用堆棧應該有這個信息,但StackFrame似乎沒有公開有關每個框架執行的特定對象的任何信息。

+0

你可以在'GetText'中添加一個'object caller'參數。 – juharr

+0

這當然會起作用,但實際上有很多很多地方都會調用'GetText',並且我想在文本來自特定的類時交換文本。 – Rollie

+1

你只需要讓自己進入一種情況,即維護一個巨大的開關或if-else-if構造。這在這裏不是很好用的OO。你應該簡單地在這裏實現一個通用的接口或子類。每個ApiController都可以有自己的GetText實現。或者你可以在每個資源類上使用通用的。或者你可以將類傳遞給GetText方法,如果你真的需要的話,但它看起來並不像你真的在這裏做的那樣。有一種更好的實現方式,不涉及你現在要做的事情。 – ManoDestra

回答

1

CurrentUser應該在HttpContext.Current.User處可用,並且您可以將您的控制器從資源類別中刪除。

2

一種方法試圖「嗅」周圍環境,並基於誰在打電話產生不同的結果通常是一個壞主意。

更好的辦法是讓你的Resources類意識到什麼,它需要知道,以便作出決定,並在所有相關信息都知道的地方進行配置,例如

class MovieApiController : ApiController { 
    private string currentUser; 
    private Resources resources; 
    public string CurrentUser { 
     get { 
      return currentUser; 
     } 
     set { 
      currentUser = value; 
      resources = new Resources(currentUser); 
     } 
    } 
    // ... 

    public string Index() { 
     return resources.GetText("Color"); 
    } 
} 

class Resources { 
    private string currentUser; 
    public Resources(string currentUser) { 
     this.currentUser = currentUser; 
    } 
    public string GetText(string id) { 
     if (currentUser == "Bob") { 
      return "Red"; 
     } else { 
      return "Blue"; 
     } 
    } 
} 
+0

同意;然而,我更關心如何執行問題中指定的操作(或知道爲什麼不可能),而不是在變通方法中執行操作。我應該使用不同的示例代碼,因爲它顯然混淆了我真正想要問的東西。 – Rollie

0

看起來像callstack應該有這個信息,

爲什麼?調用堆棧指示調用方法以獲取您所在的位置 - 它沒有任何有關實例的信息

反思您的參數是決定該方法需要做什麼工作的信息。到達課程外(例如通過使用callstack或利用靜態方法,如HttpContext.Current)會限制代碼的重用性。

從你所展示的內容來看,你所需要的只是當前的用戶名(你甚至不會顯示你使用id值的位置,如果你想根據傳入的內容返回不同的東西,那麼也許你需要分開方法?

作爲一個便箋,優化程序在重組代碼時有很大的自由度,以使其更有效,因此不能保證調用堆棧甚至包含您認爲應該從源代碼中得到的內容

+0

我相信調用堆棧實際上是什麼方法將在您當前的方法完成後調用(通常也是您來自的地方)。因此,如果當前方法要返回到方法中的特定位置並將堆棧恢復到預期狀態,則應該知道該方法的'this'指針是什麼。 – Rollie

0

簡短的回答 - 你不能創建一個自定義控制器工廠,將當前控制器存儲爲當前的HttpContext的屬性,甚至不能可能證明是不可預測的。

但是,通過嘗試檢查其調用者,它對於一個類的行爲是不同的。當一個方法依賴於另一個類時,它需要通過依賴正確的類來獲得正確的行爲,調用正確的方法並傳遞正確的參數。

因此,在這種情況下,你可以

  • 有你傳遞給GetResources一個參數,告訴它什麼,它需要知道,以便返回正確的字符串。
  • 創建Resources類的更具體的版本,那麼你需要什麼
  • 聲明

    public interface IResources 
    { 
        string GetText(string id); 
    } 
    

而且具有實現​​多個類,使用依賴注入提供正確的實施,這控制器。理想情況下,這是最好的場景。 MovieApiController不知道​​的執行情況。它只知道有一個​​的實例可以滿足它的需要。而Resource類不知道什麼是調用它。無論怎樣稱呼,它的表現都是一樣的。

這將是這樣的:

public class MovieApiController : ApiController 
{ 
    private readonly IResources _resources; 

    public MovieApiController(IResources resources) 
    { 
     _resources = resources; 
    } 

    public string Index() 
    { 
     return _resources.GetText("Color"); 
    } 
} 

注意如何控制不知道的Resources類東西。它只知道它有一些實現​​的東西,它使用它。

如果您使用的是ASP.NET Core,則依賴注入是built in。 (這裏有一些關於一般概念的很好的閱讀。)如果你使用的東西比較老,那麼你仍然可以添加它。

http://www.asp.net/mvc/overview/older-versions/hands-on-labs/aspnet-mvc-4-dependency-injection - 這張圖片的價值1000字描述這個概念。 http://www.c-sharpcorner.com/UploadFile/dacca2/implement-ioc-using-unity-in-mvc-5/

其中一些建議首先理解「控制反轉」。您可能會發現,根據示例實施某些內容會更容易,而不會先嚐試理解它。當你看到它的作用時,理解就來了。

相關問題