views:

107

answers:

3

I want to know if it's possible to retrieve the variables name from when it was passed into a certain function. For example, if I call parseId(myId) to a function with the signature parseId(id), i can obviously retrieve the value of 'id'. However, is there any way I can retrieve 'myId' as a string (without passing it as another value)?

Specifically in vb.net, but I'm interested in how it would work in any given language.

+1  A: 

No, you can't do that in the normal sense. What are you really trying to accomplish with this?

Joel Coehoorn
I'm playing with some possibilities. One example is a function to ease passing parameters to a stored procedure. A function would take a queue of all of the parameters and the stored procedure's name. Variables would be named with the same naming convention as in the stored procedure itself. This function would parse the values in the queue and essentially "load" the procedure to get called. A bit frivolous, yes. I'm just exploring possibilities :)
Chris
@Chris: Experiment: Right-click your project. Add->Component.Use Server Explorer, and drag the stored procedure onto the design surface. It should create a SqlCommand with the Parameters collection configured. No need to conform programming language variable names to database parameter names.
John Saunders
@John: Correct. I already can already do it this way. I'm just looking to learn something new :) I already have parts to this put in another function to avoid repetition but there still seems to be quite a bit of it.
Chris
+1  A: 

You can do this in .NET 3.5 and above using expression trees; I'll knock up a C# example, and try to run it through reflector for VB...

C#:

static void Main()
{
    int i = 17;
    WriteLine(() => i);
}
static void WriteLine<T>(Expression<Func<T>> expression)
{
    string name;
    switch (expression.Body.NodeType)
    {
        case ExpressionType.MemberAccess:
            name = ((MemberExpression)expression.Body).Member.Name;
            break;
        default:
            throw new NotSupportedException("Give me a chance!");
    }
    T val = expression.Compile()();
    Console.WriteLine(name + "=" + val);
}


The VB is below, but note that the VB compiler seems to use different names (like $VB$Local_i, not i):

Sub Main()
    Dim i As Integer = 17
    WriteLine(Function() i)
End Sub

Private Sub WriteLine(Of T)(ByVal expression As Expression(Of Func(Of T)))
    If (expression.Body.NodeType <> ExpressionType.MemberAccess) Then
        Throw New NotSupportedException("Give me a chance!")
    End If
    Console.WriteLine((DirectCast(expression.Body, MemberExpression).Member.Name
        & "=" & Convert.ToString(expression.Compile.Invoke)))
End Sub
Marc Gravell
This looks like a really interesting solution. However, I'm using .net 2.0
Chris
+1  A: 

This is all just random thoughts.. feel free to dismiss or not ;-p

Re your comment about use with stored procedures... if you want to go that route, I wouldn't mess around with the local variable names; that is an implementation detail. However, you could expose those details on an interface method and use the names from there, since that is more formalised - for example (C#):

interface ICustomerRepository {
    Customer GetById(int id); // perhaps an attribute to name the sproc
}

You can use similar expression-tree parsing (as discussed here) to get the name and value of the parameter, for example:

var repoWrapper = new Repo<ICustomerRepository>();
int custId = 12345;
var cust = repoWrapper.Execute(r => r.GetById(custId));

Here we'd want to resolve the argument to GetById as "id" (not "custId"), with value 12345. This is actually exactly what my protobuf-net RPC code does ;-p (just don't ask me to translate it to VB - it is hard enough to write it in a language you know well...)

Marc Gravell