我想这样做的一般原因是:
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%可靠的。似乎callstack应该有这些信息,但是StackFrame
似乎没有公开任何关于每个帧执行的特定对象的信息。
答案 0 :(得分: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";
}
}
}
答案 1 :(得分:1)
CurrentUser
应该在HttpContext.Current.User
处可用,您可以将控制器从资源类中删除。
答案 2 :(得分:0)
似乎callstack应该有这个信息,
为什么呢?调用堆栈指示调用方法以获取您所在的位置 - 它没有关于实例的任何信息。
重新考虑您的参数,决定该方法需要哪些信息来完成其工作。到达课外(例如,通过使用callstack或利用HttpContext.Current
等静态方法)限制了代码的可重用性。
根据您显示的内容,您只需要当前用户名(您甚至不会显示使用id
值的位置。如果您想根据传入的内容返回不同的内容,那么可能你需要单独的方法吗?
作为旁注,优化器在重新组织代码方面具有很大的自由度,使其更有效,因此无法保证调用堆栈甚至包含您认为应该从源代码中提供的内容。
答案 3 :(得分:0)
简短回答 - 您不能创建一个自定义控制器工厂,将当前控制器存储为当前HttpContext
的属性,甚至可能无法预测。
但是,通过尝试检查其调用者,一个类的行为方式确实不好。当一个方法依赖于另一个类时,它需要通过依赖正确的类,调用正确的方法并传递正确的参数来获得正确的行为。
所以在这种情况下你可以
GetResources
的参数,告诉它需要知道什么才能返回正确的字符串。Resources
类,以满足您的需要声明
public interface IResources
{
string GetText(string id);
}
并且有多个实现IResources
的类,使用依赖注入为该控制器提供正确的实现。理想情况下,这是最好的方案。 MovieApiController
对IResources
的实施一无所知。它只知道有一个IResources
的实例可以满足它的需要。并且Resource
类对调用它的内容一无所知。无论什么叫它,它的行为都是一样的。
看起来像这样:
public class MovieApiController : ApiController
{
private readonly IResources _resources;
public MovieApiController(IResources resources)
{
_resources = resources;
}
public string Index()
{
return _resources.GetText("Color");
}
}
注意控制器对Resources
类没有任何了解。它只知道它有一些实现IResources
并且它使用它的东西。
如果您使用的是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/
其中一些建议首先理解“控制反转”。您可能会发现根据示例实现某些内容更容易,而不首先尝试理解它。当你看到它的作用时,就会有这种理解。