从字符串表达式中获取值,例如“添加监视”功能

时间:2016-07-12 12:31:09

标签: c# wpf

string nthItem =  "ufmobj.ufmLines[0].ufmLines[1].ufmLines[1].ufmLines[1].ufmLines[2].ufmLines[2].elementTag";

 // Tried reflection method, but giving null exception
 var result = typeof(UFMLine).GetField(nthItem).GetValue(ufmobj);

这个ufmobj在窗口加载时完全填充。

在我的按钮中单击wpf窗口后面的xaml代码...

{{1}}

因此,当打开监视窗口并获取nthItem名称的值时,它会给出适当的值。

如何在后面的代码中获取它或者我没有正确使用反射?

感谢。

2 个答案:

答案 0 :(得分:1)

"名称"变量(ufmobj)可能是一个问题,因为它可能会在发布版本中丢失,但如果您不介意实现自己的解析器,则可以通过反射来实现。

  1. 拆分路径(您选择的语法)
  2. 逐个解析一个路径段
  3. 确定路径是否为字段/属性/索引器/方法/等。
  4. 重复完成
  5. 这是一个让你前进的小片段(远非完整,但适合你的例子):

    解析单个字段或属性

    private object GetFieldOrProperty(object obj, string name)
    {
        Type objType = obj.GetType();
    
        if (objType.GetField(name) != null)
            return objType.GetField(name).GetValue(obj);
        if (objType.GetProperty(name) != null)
            return objType.GetProperty(name).GetValue(obj, null);
        return null;
    }
    

    解决整个路径:

    private object Resolve(object parent, string path)
    {
        string[] paths = path.Split('.');
    
        foreach (string p in paths)
        {
            if (p.EndsWith("]"))
            {
                int start = p.IndexOf("[");
                string property = p.Substring(0, start);
                string index = p.Substring(start + 1, p.Length - start - 2);
    
                parent = GetFieldOrProperty(parent, property);
                if (parent == null)
                    return null;
    
                foreach (PropertyInfo info in parent.GetType().GetProperties())
                {
                    if (info.GetIndexParameters().Length < 1) continue;
    
                    parent = info.GetValue(parent, new object[] {int.Parse(index)});
                    break;
                }
            }
            else
            {
                parent = GetFieldOrProperty(parent, p);
                if (parent == null)
                    return null;
            }
        }
        return parent;
    }
    

    测试用例:

    UFMLine ufmobj = new UFMLine();
    ufmobj.ufmLines.Add(new UFMLine());
    ufmobj.ufmLines[0].ufmLines.Add(new UFMLine());
    ufmobj.ufmLines[0].ufmLines[0].ufmLines.Add(new UFMLine{property = "Success"});
    Debug.WriteLine(Resolve("ufmLines[0].ufmLines[0].ufmLines[0].property.Length", ufmobj));
    
      

    7(&#34;成功&#34;的长度)

答案 1 :(得分:0)

您可以将UFMLine课程的字段更改为公共媒体资源:

public class UFMLine
{
    public UFMTemplate elementTag { get; set; }
    public int posX1 { get; set; }
    public int posY1 { get; set; }
    public int posX2 { get; set; }
    public int posY2 { get; set; }
    public string property { get; set; }
    public string hierStr { get; set; } = string.Empty;
    public List<UFMLine> ufmLines { get; set; } = new List<UFMLine>();
}

现在,您可以在nthItem之后使用"ufmobj."字符串中的部分作为绑定路径,您可以使用ufmobj作为源:

var binding = new Binding
{
    Source = ufmobj,
    Path = new PropertyPath("ufmLines[0].ufmLines[1].ufmLines[1].ufmLines[1].ufmLines[2].ufmLines[2].elementTag")
};

要使用此Binding,您还需要一个目标依赖项属性,您可以在这样的辅助类中声明:

public class BindingHelper : DependencyObject
{
    public static readonly DependencyProperty ResultProperty =
        DependencyProperty.Register("Result", typeof(object), typeof(MainWindow));

    public object Result
    {
        get { return GetValue(ResultProperty); }
        set { SetValue(ResultProperty, value); }
    }
}

最后,您将Binding分配给Target属性,然后检索结果值,如下所示:

var bindingHelper = new BindingHelper();
BindingOperations.SetBinding(bindingHelper, BindingHelper.ResultProperty, binding);
var result = bindingHelper.Result;