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?

Vivendi
  • 20,047
  • 25
  • 121
  • 196
  • I've provided `GetPropertyValue` method that will suit your needs in [this answer](http://stackoverflow.com/questions/19936888/c-sharp-developing-net3-5-using-reflection-to-get-set-values-to-nested-properti/19938840#19938840) – Konrad Kokosa Dec 10 '13 at 09: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 – Vivendi Dec 10 '13 at 09:40
  • it will be enough, I'm going to provide an answer with proper example. – Konrad Kokosa Dec 10 '13 at 09:48
  • @Vivendi the only way to execute dynamic code would be via [CodeDOM](http://msdn.microsoft.com/en-us/library/y2k85ax6.aspx). However, you could do this using reflection - it just won't be as simple as you would like it to be. – James Dec 10 '13 at 10:00

1 Answers1

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;
}
Community
  • 1
  • 1
Konrad Kokosa
  • 16,563
  • 2
  • 36
  • 58
  • +1 the idea of the `container` is a nice touch. This could be further improved by making `GetPropertyValue` generic. – James Dec 10 '13 at 10:10
  • 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. – Vivendi Dec 10 '13 at 10:25