9
private void Method1()
{
    //Do something
    Log("Something","Method1");
}

private void Method2()
{
    //Do something
    Log("Something","Method2");
}

private void Log(string message, string method)
{
    //Write to a log file
    Trace.TraceInformation(message + "happened at " + method);
}

I have several methods like Method1 and Method2 above, and i would like some way pass the method's name as a parameter, without manually editing the code.

Is that possible?

gorkem
  • 103
  • 1
  • 2
  • 9
  • 3
    There is a new attribute (I think in 4.5 and needs the most recent compiler) called [`CallerMemberNameAttribute`](http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute(v=vs.110).aspx) that does exactly this, but at compile time with a string literal. Alternatively, you can use linq expressions and query the expression itself for the name, this is frequently done for properties an `INotifyPropertyChanged`, etc. – Adam Houldsworth Jan 20 '14 at 09:42
  • 1
    Instead of passing Method Name you can use Reflection – Amit Bisht Jan 20 '14 at 09:43
  • 1
    Please refer to http://stackoverflow.com/questions/2652460/c-sharp-how-to-get-the-name-of-the-current-method-from-code – Uri Y Jan 20 '14 at 09:44
  • Possible duplicate of [Can you use reflection to find the name of the currently executing method?](https://stackoverflow.com/questions/44153/can-you-use-reflection-to-find-the-name-of-the-currently-executing-method) – Michael Freidgeim Oct 08 '18 at 08:07

3 Answers3

20

As of C# 5, this is really easy using caller info attributes:

private void Method1()
{
    //Do something
    Log("Something");
}

private void Method2()
{
    //Do something
    Log("Something");
}

private void Log(string message, [CallerMemberName] string method = null)
{
    //Write to a log file
    Trace.TraceInformation(message + "happened at " + method);
}

In terms of getting this working:

  • You must be using the C# 5 (or later) compiler, otherwise it won't know to handle the attributes specially
  • The attributes have to exist in your target environment. Options there:
    • In .NET 4.5 the attributes are simply present
    • For .NET 4 you can use the Microsoft.Bcl NuGet package
    • For earlier versions of .NET, copy the attribute declaration into your own code, making sure you use the same namespace. When you later move to a new version of .NET, you'll need to remove it again.
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Excellent answer Jon. Just curious: In case of `unit testing` how exactly this attribute behave ? Can we mock up ? – now he who must not be named. Jan 20 '14 at 09:58
  • 1
    @nowhewhomustnotbenamed.: It's a compile-time thing - the compiler notices that the parameter has been decorated with the attribute and has a default value of null, and the caller hasn't supplied an argument, so it uses the member name instead. I'm not sure what sort of mocking you're talking about, but you can easily just pass an argument explicitly (e.g. `Log("message", "NotARealMethod")`) – Jon Skeet Jan 20 '14 at 09:59
  • Thanks Jon. `Optional Parameters`. Makes sense. :) – now he who must not be named. Jan 20 '14 at 10:04
  • +1 is it worth adding in details on creating the attribute yourself if in an older version of .NET but still using c# 5 compiler? – Joe Jan 20 '14 at 11:02
  • 1
    @JoeStead: I'll add a short note, but not full details. – Jon Skeet Jan 20 '14 at 11:13
5

Excellent answer from Jon Skeet.

However, if you don't use .NET 4.5 , you can try reflection. How ever you should know that reflection must be used only when it is absolutely necessary. Do not over-use it for the sake of using it.

Coming back, You could do something like,

 using System.Reflection; //include Reflection namespace

 Console.WriteLine(MethodBase.GetCurrentMethod().Name) //Get the method-name of the current method

In your case, it would be like below,

private void Method1()
{
    //Do something
    Log("Something", System.Reflection.MethodBase.GetCurrentMethod().Name);
}

private void Method2()
{
    //Do something
    Log("Something", System.Reflection.MethodBase.GetCurrentMethod().Name);
}

private void Log(string message, string method)
{
    //Write to a log file
    Trace.TraceInformation(message + "happened at " + method);
}

EDIT:

As per the below comments from @Jon Skeet's, if you want .Net 4.5 kind of fancy and neat implementation, check out the Micrsoft.Bcl NUGET Package.

  • I can't use .NET 4.5 or 5, so reflection seems to only way do it. – gorkem Jan 20 '14 at 10:07
  • What is the point? You can simply put a method name in the parameter, because you actually know its name, when you write code. This is not a solution to the problem, just helps copy-paste code easier. – Artyom Neustroev Jan 20 '14 at 10:10
  • @ArtyomNeustroev: Since, the OP cannot use `.NET 4 or .NET 4.5`, i think he is left with the above choice. What if `method-name` changes in future or if there are more methods? While this can help copy-paste code easier, there is no other elegant solution (if you don't use .NET 4 Or .Net 4.5) – now he who must not be named. Jan 20 '14 at 10:14
  • 1
    @gorkem: No, this isn't the only way to do it. If you can use a C# 5 compiler, you can add the attributes in yourself. – Jon Skeet Jan 20 '14 at 10:35
  • @JonSkeet: Thanks Jon. Do you mean that we can roll-out custom `[CallerMemberName]` even in lower versions of .net ? Kindly point me with a sample please. – now he who must not be named. Jan 20 '14 at 10:53
  • 1
    @nowhewhomustnotbenamed.: Yes, you can. In .NET 4, just use the `Micrsoft.Bcl` NuGet package; for older versions just copy the attribute declaration from MSDN, making sure you put it in the same namespace as the real one. – Jon Skeet Jan 20 '14 at 10:56
  • @JonSkeet: Thanks Jon, checking it out. – now he who must not be named. Jan 20 '14 at 10:58
0

Aspect Oriented Programming (AOP) usually allows to achieve such tasks. You can have a look at the free version of PostSharp, especially the Logging aspect is helpful in your case.

Your code then looks like this:

[LogAspect("Something")]
void Method1(string name)
{

}

You can use PostSharp down to .NET framework 2.0.

Thomas Weller
  • 55,411
  • 20
  • 125
  • 222