通过字符串从本地变量获取属性

时间:2013-12-10 09:23:40

标签: c# reflection invoke

在方法内部,我进行一些Web服务调用以获取数据,如下所示:

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

我还有一个XML文件,用户可以在其中告诉要映射的属性。 XML类似如下:

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

所以我基本上想要做的是执行mapper属性中的字符串。所以我有这样的事情:

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

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

    var value = Invoke(usernameProperty);
}

所以它应该像我在我的代码中手动调用var value = user.username.value;一样。

但我如何从string调用此操作?

1 个答案:

答案 0 :(得分:3)

通常,您无法在运行时获取局部变量的值(请参阅this question以供参考),但基于我自己的answer from another question,您可以使用方法GetPropertyValue来解决创建具有所需属性的本地对象时出现此问题:

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;
}