C# 是否可以在方法中获取调用实例?
我想这样做的一般原因是:C# 是否可以在方法中获取调用实例?,c#,asp.net,C#,Asp.net,我想这样做的一般原因是: class MovieApiController : ApiController { public string CurrentUser {get;set;} // ... public string Index() { return Resources.GetText("Color"); } } class Resources { static string GetText(string id)
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
似乎没有公开关于每个帧在其上执行的特定对象的任何信息。CurrentUser
应该在HttpContext.Current.User
上可用,并且您可以将控制器排除在资源类之外 CurrentUser
应该可以在HttpContext.Current.User
上找到,并且您可以将控制器排除在资源类之外 一种方法试图“嗅探”周围环境,并根据发出呼叫的人产生不同的结果,这通常是一个坏主意
更好的方法是让您的资源
类知道它需要知道什么才能做出决策,并将其配置在一个所有相关信息都已知的位置,例如
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";
}
}
}
对于一个方法来说,尝试“嗅探”它周围的环境,并根据发出调用的人产生不同的结果,这通常是一个坏主意 更好的方法是让您的
资源
类知道它需要知道什么才能做出决策,并将其配置在一个所有相关信息都已知的位置,例如
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";
}
}
}
看来callstack应该有这些信息
为什么??调用堆栈指明了调用哪些方法来达到您的目的-它没有任何关于实例的信息
重新考虑您的参数,确定该方法需要哪些信息来完成其工作。到达类外(例如,通过使用调用堆栈或利用静态方法,如HttpContext.Current
)限制代码的可重用性
从您所显示的内容来看,您所需要的只是当前用户名(您甚至没有显示在哪里使用id
值。如果您希望根据传入的内容返回不同的内容,那么您可能需要单独的方法
作为旁注,优化器在重新组织代码以提高效率方面有很大的自由度,因此不能保证调用堆栈甚至包含您认为应该来自源代码的内容
看来callstack应该有这些信息
为什么?调用堆栈指出了调用什么方法来达到您的目的-它没有任何关于实例的信息
重新考虑您的参数,确定方法需要哪些信息来完成其工作。到达类外(例如,通过使用调用堆栈或利用静态方法,如HttpContext.Current
)会限制代码的可重用性
从您所显示的内容来看,您所需要的只是当前用户名(您甚至没有显示在哪里使用id
值。如果您希望根据传入的内容返回不同的内容,那么您可能需要单独的方法
另一方面,优化器在重新组织代码以提高效率方面有很大的自由度,因此不能保证调用堆栈包含您认为应该来自源代码的内容。简短回答-您不能,除非创建一个自定义控制器工厂,将当前控制器存储为t的属性他认为当前的HttpContext是不可预测的,即使是这样 但是,如果一个类试图检查它的调用者而表现出不同的行为,那么这确实是不好的。当一个方法依赖于另一个类时,它需要通过依赖正确的类、调用正确的方法和传递正确的参数来获得正确的行为 所以在这种情况下,你可以
- 有一个传递给
的参数,告诉它需要知道什么才能返回正确的字符串GetResources
- 创建一个更具体的
类版本,以满足您的需要Resources
- 申报
public interface IResources { string GetText(string id); }
IResources
的类,使用依赖项注入为该控制器提供正确的实现。理想情况下,这是最好的方案。MovieApicController
对IResources
的实现一无所知。它只知道有一个IResourc的实例es
将执行它需要的操作。而资源
类不知道调用它的内容。无论调用什么,它的行为都是一样的
看起来是这样的:
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,那么依赖项注入就是。(关于一般概念,这里有一些很好的阅读。)如果您使用的是旧版本,那么您仍然可以添加它
-这是一幅1000字的图片,用于描述概念。
其中一些建议理解“控制反转”首先。您可能会发现,只根据示例实现某些内容而不首先尝试理解它更容易。当您看到它的功能时,就会理解它。简短回答-您不能,除非创建一个自定义控制器工厂,将当前控制器存储为当前
HttpContext
的属性,然后即使这样,也可能被证明是不可预测的
但是,如果一个类试图检查它的调用者而表现出不同的行为,那么这确实是不好的。当一个方法依赖于另一个类时,它需要通过依赖正确的类、调用正确的方法和传递正确的参数来获得正确的行为
所以在这种情况下,你可以
- 有一个传递给
的参数,告诉它需要知道什么才能返回正确的字符串GetResources
- 创建一个更具体的v