Archive

Posts Tagged ‘reflection’

emulating nameof ?

October 4th, 2014 antonio elena No comments

As you might now C# 6.0 will include the new nameof keyword to allow code like this

void MyMethod(string parameter1)
{
  if(parameter1 == null)
  	throw new ArgumentNullException(nameof(parameter1));

	// ....
}

instead of having to pass the name as a string as before

void MyMethod(string parameter1)
{
  if(parameter1 == null)
  	throw new ArgumentNullException("parameter1");

	// ....
}

So far, in some of my code I was using a variation of this idea not available as such in previous versions of the language. Renaming the code to actually use a user defined function with the same “nameof” name we could have something like this (I am showing with just a quick and dirty console attribute):

static void Main ( string [] args )
        {
            MyMethod ( null );
        }
        static void MyMethod ( string parameter1 )
        {
            throw new ArgumentNullException ( nameof ( parameter1 ) );
        }
        static string nameof ( object p )
        {
            // get previous stack frame
            StackFrame frame = new StackFrame ( 1 );
            // inspect the caller
            MethodBase method = frame.GetMethod ();
            // and get the name of the first parameter defined in the caller's signature
            return frame.GetMethod ().GetParameters ().First ().Name;
        }
    }

Naturally, this is not so straigthforward when there are more arguments and the one we want might not be the first one, but the nth argument in the signature. The first solution that comes to mind then is passing the position when throwing the ArgumentNullException:

static void MyMethod ( string parameter0, string parameter1 )
        {
            try
            {
                throw new ArgumentNullException ( nameof ( parameter1, 1 ) );
            }
            catch ( Exception ex )
            {
                Console.WriteLine (ex.Message);
            }
            Console.ReadLine ();
        }
        static string nameof ( object p, int pos = 0 )
        {
            // get previous stack frame
            StackFrame frame = new StackFrame ( 1 );
            // inspect the caller
            MethodBase method = frame.GetMethod ();
            // and get the name of the first parameter defined in the caller's signature
            return frame.GetMethod ().GetParameters ().ElementAt ( pos ).Name;
        }

However, even when declaring the position as an optional parameter so as to have a cleaner case when the parameter we are interested in is the first one, this is not perfect as it introduces an additional element that the caller has to care about.

But at least, you avoid hardcoding parameter names in situation like this, which is a good thing when you want to rename objects. It’s easier this way.

The new nameof expression, however, is not limited to scenarios like this. You can actually get a hold of any programming construct via nameof.

Take this example from msdn magazine

[TestClass]
  public class NameofTests
  {
    [TestMethod]
    public void Nameof_ExtractsName()
    {
      Assert.AreEqual<string>("NameofTests", nameof(NameofTests));
      Assert.AreEqual<string>("TestMethodAttribute",
        nameof(TestMethodAttribute));
      Assert.AreEqual<string>("TestMethodAttribute",
        nameof(
         Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute));
      Assert.AreEqual<string>("Nameof_ExtractsName",
        string.Format("{0}", nameof(Nameof_ExtractsName)));
      Assert.AreEqual<string>("Nameof_ExtractsName",
        string.Format("{0}", nameof(
        CSharp6.Tests.NameofTests.Nameof_ExtractsName)));
    }
  }

With reflection we can do similar things, but it all feels quite clumnsy, as we cannot really do something like this:

 static void Main ( string [] args )
     {
         // apparently you cannot pass 'Main' like this...
         Console.WriteLine ( nameof ( Main ) );
     }
     // this is fantasy, there is no such 'MethodGroup' class
     static string nameof ( MethodGroup m )
     {
         // get the name of such MethodGroup instance...
         return null;
     }

Sadly there is no such thing as a MethodGroup.A MethodGroup is an internal type used by the compiler in order to keep track of the expression so far. It’s not an LValue and you can’t put it in a variable; it doesn’t inherit from anything and it doesn’t have a .NET Type.

Apart from the fact that class MethodGroup does not exist, there is a workaround, that feels also not so good, that involves creating an Action and to enable casting to a delegate like this:

static void Main ( string [] args )
{
	Console.WriteLine ( nameof ( new Action ( Method ) ) );
}
static void MyMethod ()
{
}
static string nameof ( Delegate d )
{
    return d.Method.Name;
}

Or we can leverage expression trees:

static void Main ( string [] args )
        {
            Console.WriteLine ( nameof ( () => Main(args) ) );
        }
        static void MyMethod ()
        {
        }
        static string nameof ( Expression<Action> expr )
        {
            // get previous stack frame
            StackFrame frame = new StackFrame ( 1 );
            // inspect the caller
            MethodBase method = frame.GetMethod ();
            return method.Name;
        }

Or without using StackFrame at all:

 static void Main ( string [] args )
        {
            Console.WriteLine ( nameof ( () => Main(args) ) );
        }
        static void MyMethod ()
        {
        }
        static string nameof ( Expression<Action> expr )
        {
            var call = ( MethodCallExpression ) expr.Body;
            return call.Method.Name;
        }

In that way we can access our Main method.

There are other options…. for example leveraging AOP frameworks such as PostSharp or Fody to introduce IL-weaving code that simulates the same effect.

A simpler option is to create a simple Enum to tell our makeshift nameof to inspect either our class name or other higher level constructs such as those from the real nameof example. For example:

public enum InspectionLevel
    {
        CLASS,
        ASSEMBLY,
        ATTRIBUTES
    }

And the rest would be standard reflection code. No big deal. The new nameof of course makes things much easier in this sense.

spacer
Categories: .net Tags: .net, c++, reflection
gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.