C # passes any method as a parameter

When registering, you always fall into string literals.

I solved this well for properties, fields, and variables by passing Expression<Func<T>> expression (as explained here ), so you can do something like this:

 public void Demo(string someArgument) { LogFrameWork.LogLine("Demo"); // goal is to get rid of these string literals LogFramework.Log(() => someArgument); } 

I want to do something similar for the Demo method itself:

 public void Demo(string someArgument) { LogFramework.Log(this.Demo); } 

I tried things like this:

 public static void Log(Delegate method) { string methodName = method.Method.Name; LogLine(methodName); } 

and this:

 public static void Log(Action method) { string methodName = method.Method.Name; LogLine(methodName); } 

But I get compiler errors like this:

 Argument 1: cannot convert from 'method group' to 'System.Delegate' Argument 1: cannot convert from 'method group' to 'System.Action' 

I could introduce a bunch of overloads using Func <...> and Action <...> , but that sounds too complicated.

Is there any way to cover this for any method with any number of parameters and optional result?

- Jeroen

PS: I think this question may have some significance here, but there are no answers that made me feel aha :-)

+6
methods c # parameters
source share
5 answers

Instead of trying to pass a method as a parameter to your registrar, look at it in terms of identifying the registrar as the calling method.

Here's an example (pseudo):

Registrar Class

 public void Debug( string message ) { message = string.Format( "{0}: {1}", GetCallingMethodInfo(), message ); // logging stuff } /// <summary> /// Gets the application name and method that called the logger. /// </summary> /// <returns></returns> private static string GetCallingMethodInfo() { // we should be looking at the stack 2 frames in the past: // 1. for the calling method in this class // 2. for the calling method that called the method in this class MethodBase method = new StackFrame( 2 ).GetMethod(); string name = method.Name; string type = method.DeclaringType.Name; return string.Format( "{0}.{1}", type, name ); } 

In any place where the registrar is used:

 // resides in class Foo public void SomeMethod() { logger.Debug("Start"); } 

The Foo.SomeMethod: Start will be as follows: Foo.SomeMethod: Start

+3
source share

You can also achieve this without using ExpressionTrees through System.Diagnostics.StackTrace .

 StackTrace trace = new StackTrace(); 

And then:

 trace.GetFrame(0).GetMethod().Name 

To get MethodInfo, and then the name of the current method or:

 trace.GetFrame(1).GetMethod().Name 

To get the calling method.

+5
source share

It is much more complicated than it seems. I think you might be best off using the common Func and Action overloads, but there is a way to do this using expression trees. Here is an example in LINQPad:

 public static void Log(Expression<Action> expr) { Console.WriteLine(((MethodCallExpression)expr.Body).Method.Name); } void Main() { Log(() => DoIt()); Log(() => DoIt2(null)); Log(() => DoIt3()); } public void DoIt() { Console.WriteLine ("Do It!"); } public void DoIt2(string s) { Console.WriteLine ("Do It 2!" + s); } public int DoIt3() { Console.WriteLine ("Do It 3!"); return 3; } 

It is output:

  Doit
 Doit2
 Doit3 

Note that I had to use lambdas and specify dummy arguments when calling the Log method.

This is based on Fedor Soikin's excellent answer .

+5
source share

You can define a delegate and then accept that delegate as a parameter.

 public delegate void DemoDelegate(string arg); public void MyMethod(DemoDelegate delegate) { // Call the delegate delegate("some string"); } 

You can call MyMethod as follows:

 MyMethod(delegate(string arg) { // do something }); 

or

 void MethodThatTakesAString(string value) { // do something } MyMethod(MethodThatTakesAString); 

See this link for more information:

http://msdn.microsoft.com/en-us/library/aa288459(v=vs.71).aspx

0
source share

Try the following:

 /// <summary> /// Trace data event handler delegate. /// </summary> /// <returns>The data to write to the trace listeners</returns> public delegate object TraceDataEventHandler(); public static class Tracing { /// Trace a verbose message using an undefined event identifier and message. /// </summary> /// <param name="message">The delegate to call for the trace message if this event should be traced.</param> [Conditional("TRACE")] public static void TraceVerbose(TraceMessageEventHandler message) { ... your logic here } } 

Then you can do ...

 Tracing.TraceVerbose(() => String.Format(...)); 

Hope I understood your question correctly ... does this do what you want?

0
source share

All Articles