【问题标题】:Get property from local variable by string通过字符串从局部变量中获取属性
【发布时间】:2013-12-10 09:23:40
【问题描述】:

在一个方法中,我调用了一些 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 调用此操作?

【问题讨论】:

  • 我在this answer 中提供了适合您需求的GetPropertyValue 方法
  • 我不确定这是否是我正在寻找的答案。这是关于我需要执行的方法内部的局部变量。我想我需要更多的Eval 功能。但不幸的是,这并不像我想象的那么容易
  • 这就够了,我会用适当的例子来回答。
  • @Vivendi 执行动态代码的唯一方法是通过CodeDOM。但是,您可以使用反射来做到这一点 - 它不会像您希望的那样简单。

标签: c# reflection invoke


【解决方案1】:

一般来说,你不能在运行时获取局部变量的值(参考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;
}

【讨论】:

  • +1 container 的想法很不错。这可以通过将GetPropertyValue 设为通用来进一步改进。
  • 非常感谢,这似乎可以解决问题!我在代码中将result.GetValue(currentObj) 都更改为result.GetValue(currentObj, null),因为它需要两个参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-22
  • 1970-01-01
  • 1970-01-01
  • 2012-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多