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