简体   繁体   English

有没有办法确定哪个类在.NET中称为静态方法

[英]Is there a way to determine which class called a static method in .NET

We have a central STATIC method that get's called from many different locations of our ASP.NET application. 我们有一个中央STATIC方法,可以从ASP.NET应用程序的许多不同位置调用。

I need to add some conditional logic to the static method that needs to run only if the method was called from a specific class. 我需要向静态方法添加一些条件逻辑,只有在从特定类调用方法时才需要运行。 One approach would be to add an additional parameter to the static method's signature -- some kind of enum that would represent which class called this static method, but I was hoping .NET offered a more elegant approach. 一种方法是在静态方法的签名中添加一个额外的参数 - 某种枚举可以表示哪个类称为静态方法,但我希望.NET提供更优雅的方法。

EDIT: See Sample Code below 编辑:请参阅下面的示例代码

I am trying to modify how exceptions are handled. 我试图修改异常的处理方式。 Currently, if we are processing 1000 checks, and there is an exception inside the loop at check 500, checks 500 - 1000 will not be processed. 目前,如果我们正在处理1000次检查,并且在检查500处的循环内存在异常,则不会处理检查500-1000。

We have several screens on our website that calls this central method. 我们的网站上有几个屏幕,称之为中央方法。 One of them called Check Creation Wizard, another called ACH Creation Wizard, etc. Well for the ACH Creation Wizard, we want to handle exceptions by simply skipping a failed check, and move on to the rest of the checks. 其中一个叫做Check Creation Wizard,另一个叫做ACH Creation Wizard,等等。对于ACH Creation Wizard,我们想通过简单地跳过失败的检查来处理异常,然后继续进行其余的检查。 However, for all other wizards, we want to continue failing the remaining batch of checks if one fails. 但是,对于所有其他向导,如果一个失败,我们希望继续对剩余的一批检​​查失败。

public static string GenerateChecks(List<CheckJob> checkJobs)
{
    foreach (CheckJob check in checkJobs)
    {
        try
        {
            bool didGenerate = DoGenerate(check);
            if(didGenerate)
            {
                Account acct = LoadAccount(check.GetParent());
                ModifyAccount(acct);
                SaveAcct(acct);
            }
        }           
        catch (Exception ex)
        {
            if (Transaction.IsInTransaction)
            {
                Transaction.Rollback();
            }

            throw;
        }
    }
}

This all smells from afar. 这一切都远远闻到了。 You can have this in many ways, but detecting the calling class is the wrong way. 你可以通过多种方式实现这一点,但检测调用类是错误的。

Either make a different static method for this specific other class, or have an additional argument. 为这个特定的其他类创建一个不同的静态方法,或者有一个额外的参数。

If you insist on detecting the caller, this can be done in several ways: 如果您坚持检测呼叫者,可以通过以下几种方式完成:

  1. Use the stack trace: 使用堆栈跟踪:

     var stackFrame = new StackFrame(1); var callerMethod = stackFrame.GetMethod(); var callingClass = callerMethod.DeclaringType; // <-- this should be your calling class if(callingClass == typeof(myClass)) { // do whatever } 
  2. If you use .NET 4.5, you can have caller information. 如果您使用.NET 4.5,则可以获得呼叫者信息。 Not specifically the class, but you can get the caller name and source file at the time of compilation. 不是特定的类,但您可以在编译时获取调用者名称和源文件。 Add a parameter with a default value decorated with [CallerMemberName] or [CallerFilePath] , for example: 添加一个带有[CallerMemberName][CallerFilePath]修饰的默认值的参数,例如:

     static MyMethod([CallerFilePath]string callerFile = "") { if(callerFile != "") { var callerFilename = Path.GetFileName(callerFile); if(callerFilename == "myClass.cs") { // do whatever } } } 
  3. Simply use an additional parameter with a default value (or any kind of different signature) 只需使用带有默认值的附加参数(或任何类型的不同签名)

Note that 1 is very slow, and 2 is just awful... so for the better yet: use a different method if you need a different process 请注意,1非常慢,2只是非常糟糕...所以为了更好: 如果您需要不同的过程,请使用不同的方法

Update 更新


After watching your code, it's even more clear that you want to have either two different methods or an argument... for example: 看完你的代码之后,你更清楚的是你想要两个不同的方法或一个参数...例如:

public static string GenerateChecks(List<CheckJob> checkJobs, bool throwOnError = true)
{
    //...
    catch (Exception ex)
    {
      if(throwOnError)
      {
        if (Transaction.IsInTransaction)
        {
           Transaction.Rollback();
        }
        throw;
      }
    }
}

And then pass false to that when you want to keep going 当你想要继续前进时,将false传递给那个

You never make a decision on what to do based on who called you. 你永远不会根据谁给你打电话做出决定。 You allow the caller to make that decision by providing a feature . 您允许呼叫者通过提供功能来做出决定

You want a single method to do two different things on error. 您希望单个方法在出错时执行两个不同的操作。 So either (1) write two methods, and have the caller decide which one to call, or (2) make the method take a Boolean that changes its behaviour, and have the caller decide which Boolean to pass, true or false. 所以要么(1)写两个方法,让调用者决定调用哪一个,或者(2)使方法采用改变其行为的布尔值,让调用者决定传递哪个布尔值,true或false。

Adding a parameter is definitely more "elegant". 添加参数肯定更“优雅”。 Make the parameter optional (by providing a default value, eg bool and false ) and only execute the special code if the parameter is explicitly set to true. 使参数可选(通过提供默认值,例如boolfalse ),并且仅在参数显式设置为true时才执行特殊代码。

The alternative, though not as "elegant" as you can read from the comments, would be to search the StackTrace for the calling code. 另一种选择,虽然不像你可以从评论中读到的那样“优雅”,但是可以在StackTrace中搜索调用代码。

我想,你可以使用StackTrace类,但这种逻辑并不是很好

You can use StackTrace like this 您可以像这样使用StackTrace

 static void Main(string[] args)
{
    Do();
}

static void Do()
{
    DosomethingElse();
}

private static void DosomethingElse()
{
    StackTrace stackTrace = new StackTrace();
    foreach (StackFrame Frame in stackTrace.GetFrames())
    {
        Console.WriteLine(Frame);
    }
}

and this would be the output 这将是输出

{DosomethingElse at offset 77 in file:line:column <filename unknown>:0:0}
{Do at offset 37 in file:line:column <filename unknown>:0:0}
{Main at offset 40 in file:line:column <filename unknown>:0:0}
....

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM