3

Inside a method i make a few web service calls to get data, like so:

public void SomeMethod()
{
    var user = userWS.GetUsers();
    var documents = documentWS.GetDocuments();
}

I also have an XML file in which a user can tell what property to map. The XML sort of looks like this:

<root>
  <item id="username" mapper="user.username.value" />
  <item id="document1" mapper="documents.document1.value" />
</root>

So what i basically want to do is execute to string that is inside the mapper attribute. So that i have something like this:

public void SomeMethod()
{
    var user = userWS.GetUsers();
    var documents = documentWS.GetDocuments();

    // returns: "user.username.value"
    string usernameProperty = GetMapperValueById ( "username" );

    var value = Invoke(usernameProperty);
}

So it should act as if i was calling var value = user.username.value; manually in my code.

But how can i invoke this action from a string?

4
  • I've provided GetPropertyValue method that will suit your needs in this answer Commented Dec 10, 2013 at 9:27
  • I'm not sure if that is the answer i'm looking for. This is about a local variable from inside a method that i need to execute. I think i need more of an Eval function for this. But unfortunately that isn't as easy as i thought it would be Commented Dec 10, 2013 at 9:40
  • it will be enough, I'm going to provide an answer with proper example. Commented Dec 10, 2013 at 9:48
  • @Vivendi the only way to execute dynamic code would be via CodeDOM. However, you could do this using reflection - it just won't be as simple as you would like it to be. Commented Dec 10, 2013 at 10:00

1 Answer 1

3

In general, you can't get values of local variables at runtime (see this question for reference), but based on my own answer from another question, you can use method GetPropertyValue to workaround this problem creating a local object with desired properties:

public void SomeMethod()
{
    var container = new 
    {
        user = userWS.GetUsers(),
        documents = documentWS.GetDocuments()
    }

    // returns: "user.username.value"
    string usernameProperty = GetMapperValueById ( "username" );

    var value = GetPropertyValue(container, usernameProperty);
}

static object GetPropertyValue(object obj, string propertyPath)
{
    System.Reflection.PropertyInfo result = null;
    string[] pathSteps = propertyPath.Split('.');
    object currentObj = obj;
    for (int i = 0; i < pathSteps.Length; ++i)
    {
        Type currentType = currentObj.GetType();
        string currentPathStep = pathSteps[i];
        var currentPathStepMatches = Regex.Match(currentPathStep, @"(\w+)(?:\[(\d+)\])?");
        result = currentType.GetProperty(currentPathStepMatches.Groups[1].Value);
        if (result.PropertyType.IsArray)
        {
            int index = int.Parse(currentPathStepMatches.Groups[2].Value);
            currentObj = (result.GetValue(currentObj) as Array).GetValue(index);
        }
        else
        {
            currentObj = result.GetValue(currentObj);
        }

    }
    return currentObj;
}
Sign up to request clarification or add additional context in comments.

2 Comments

+1 the idea of the container is a nice touch. This could be further improved by making GetPropertyValue generic.
Thanks alot, this seems to be doing the trick! I changed both result.GetValue(currentObj) to result.GetValue(currentObj, null) in my code, since it expects two params.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.