2016-04-07 48 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/

其中一些建议首先理解“控制反转”。您可能会发现,根据示例实施某些内容会更容易,而不会先尝试理解它。当你看到它的作用时,理解就来了。

相关问题