I am aiming to add some #if DEBUG to my methods however I don't want to edit the code I copy and Paste into each method.
Is there a generic piece of code like this:
void DoSomething()
{
#if Debug
Log("Now In " + MethodName);
#endif
}
Where MethodName is populated to equal DoSomething, or whichever Method called the Log?
If you're using .NET 4.5 you can use the CallerMemberName attribute:
public static GetCallerMemberName([CallerMemberName]string caller = null)
{
return caller;
}
Note that when calling this method you don't need to pass anything as an argument - the C# compiler does the work for you. This also means that you avoid performing reflection at runtime, which makes this method much faster.
Usage:
void DoSomething()
{
#if Debug
Log("Now In " + GetCallerMemberName()); // Logs "Now in DoSomething"
#endif
}
System.Reflection.MethodBase.GetCurrentMethod().Name
Related
My class requires additional information to properly output its status, so I've added a custom PrintSelf method taking the appropriate parameters.
However, I'm afraid there are still calls to ToString in my large project, which were not replaced by the new method. How can I find those improper calls to ToString?
I'm using VS 2015, but it does not seem to have this ability.
Throwing an exception in ToString would be an obvious way, but I don't want to do that for two reasons:
ToString can still perform a different job and output something not depending on the added parameter.
There is no way to get full code coverage, meaning it would only find a few instances of implicit calls, but not (reliably) all of them.
To override ToString and log the caller you can do like this
public override string ToString()
{
StackTrace stackTrace = new StackTrace();
StackFrame[] stackFrames = stackTrace.GetFrames();
StackFrame callingFrame = stackFrames[1];
MethodInfo method = callingFrame.GetMethod();
YourLogingMethod(method.DeclaringType.Name + "." + method.Name);
return base.ToString();
}
You can make usage of the Obsolete Attribute :
public class MyFirstClass
{
//true or false parameters indicates whether to throw
// a compile error (true) or warning (false)
[Obsolete("Please use the method PrintSelf() instead of ToString()", false)]
public overrides string ToString()
{
//Whatever code you want here
return "";
}
}
public class MySecondClass
{
public void Test()
{
mfc = new MyFirstClass();
mfc.ToString(); //Here you will get a compiler warning
}
}
So this will let you know inside Visual Studio of all the calls made to this function. Since it is only a warning, it is still possible to use it.
(note : Sorry if the syntax is not correct, I'm normally a VB .Net developper, feel free to correct it if needed.)
We have a central STATIC method that get's called from many different locations of our ASP.NET application.
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.
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.
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. 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:
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
}
If you use .NET 4.5, you can have caller information. 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:
static MyMethod([CallerFilePath]string callerFile = "")
{
if(callerFile != "")
{
var callerFilename = Path.GetFileName(callerFile);
if(callerFilename == "myClass.cs")
{
// do whatever
}
}
}
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
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
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.
Adding a parameter is definitely more "elegant". Make the parameter optional (by providing a default value, e.g. bool and false) and only execute the special code if the parameter is explicitly set to true.
The alternative, though not as "elegant" as you can read from the comments, would be to search the StackTrace for the calling code.
I think, you can use StackTrace class, but this logic is not very good
You can use StackTrace like this
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}
....
I have method public void categoriesForm_DeleteItem(int categoryID) in
public partial class Categories_View1 : System.Web.UI.Page . It is modeled after method RemoveItem from tutorial http://www.asp.net/web-forms/overview/getting-started/getting-started-with-aspnet-45-web-forms/shopping-cart .
My method contains following code:
public void categoriesForm_DeleteItem(int categoryID)
{
/* some code ommited */
if (c != null)
{
db.Categories.Remove(c);
db.SaveChanges();
Response.RedirectToRoute("CategoriesList");
//should I add return; here?
}
else
{
ModelState.AddModelError("NotFoundError", "Category not found.");
return;
}
/* code ommited */
}
Should I add return; after Response.RedirectToRoute("CategoriesList"); ?
One more question... I saw on the tutorial that the method RemoveItem returns int, what is the intent behind that return code? Where is that return code useful?
Should I add return; after Response.RedirectToRoute("CategoriesList"); ?
That depends on whether or not you want the code to return.
First, note a key difference between Response.Redirect() and Response.RedirectToRoute(). The former (older) method by default aborts the thread, which throws a ThreadAbortException. So no code after that statement would be expected to execute anyway. The latter (newer) method, however, does not. Which means any code after it will be expected to execute.
Given that, take a look at the last bit in your example...
/* code ommited */
That code will execute if you don't return from the method. If you don't want that to happen, you would either need to return from the method or structure the code such that no further code path exists after calling Response.RedirectToRoute().
A void method does not have a return type by default. If you return an object or anything, you will have runtime error.
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?
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.
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.
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.
I have a method. I want to check a condition and
if result of my condition is true throw new exception.
I need to name of method for message exception. For example :
public void MyMethod(Notifier not)
{
if(not.HasValue())
throw new Exception("MyMethod_name : " + not.Value);
}
How get name of method in the method?
Is this what you looking for?
new StackFrame(1, true).GetMethod().Name
but again playing with stack means performance hit if misused.
OR are you looking for this - http://www.csharp-examples.net/get-method-names/
OR http://heifner.blogspot.co.nz/2006/12/logging-method-name-in-c.html
OR have a look here nice notes - Get Calling function name from Called function
Hope this helps, cheers!
This approach avoids the stack issues:
public void MyMethod(Notifier not)
{
if(not.HasValue())
{
string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;
throw new Exception(methodName + ": " + not.Value);
}
}
[But note that there may occasionally be unexpected results: for example, small methods or properties are often inlined in release builds, in which case the result will be the caller's method name instead.]
Using Reflection you can get the method name.....By using the powerful reflection facilities in the framework, you can invoke the method. This involves the System.Reflection namespace and theGetMethod method.
For implementation of Reflection, take a reference to this link......
http://www.dotnetperls.com/getmethod
public void MyMethod(Notifier not)
{
StackFrame stackFrame = new StackFrame();
MethodBase methodBase = stackFrame.GetMethod();
if(not.HasValue())
throw new Exception("MyMethod_name : " + methodBase.Name);
}