2016-07-08 82 views
2

我想要做的可能有點奇怪。 但我想(這是最好的我可以解釋它)使用反射來獲取完整的類屬性樹名稱作爲字符串。獲得完整的類屬性「樹」名稱作爲字符串


成功的例子至今:

通過使用表情我能轉換:

() => Model.Cargo.Id 

到字符串:

"Model.Cargo.Id" 

我現在的問題是當我在混合使用數組時,我沒有得到數組名稱。我得到的只是最後一個屬性名稱。

不成功的例子

Model.CargoTasks[j].IsSet 

只返回我的字符串:

"IsSet" 

理想我想下面的字符串結果:

"Model.CargoTasks[0].IsSet" 

我可能會問有一點需要將結果包括在內,但如果這是可能的話,這將是幻想。


我使用來處理這些例子的代碼如下:

public static string ToMemberAccess<TResult>(this Expression<Func<TResult>> expression) 
{ 
    // Get the body of the expression 
    Expression body = expression.Body; 
    if (body.NodeType != ExpressionType.MemberAccess && body.NodeType != ExpressionType.Convert) 
    { 
     throw new ArgumentException("Property expression must be of the form '() => SomeProperty'", "expression"); 
    } 

    var memberExpression = expression.Body as MemberExpression ?? ((UnaryExpression)expression.Body).Operand as MemberExpression; 
    var stuff = GetMemberNames(memberExpression); 
    stuff.Reverse(); 

    return string.Join(".", stuff); 
} 

static List<string> GetMemberNames(MemberExpression expression, List<string> actual = null) 
{ 
    if (actual == null) actual = new List<string>(); 

    var member = expression.Member; 
    var subExp = expression.Expression as MemberExpression; 
    actual.Add(member.Name); 

    if(subExp != null) actual = GetMemberNames(subExp, actual); 

    return actual; 
} 

感謝提前!任何幫助將不勝感激!

+0

你可以只是做'expression.ToString()'非常接近 - 這將是像'()=>值(X).Model.CargoTasks [0] .IsSet' –

+0

感謝響應。不過,我已經測試過它返回的東西更像是:'Model.CargoTasks.get_Item(value(Resources.AssignTasks.AssignTasks + <> c__DisplayClass5).j).IsSet' – MitchellNZ

回答

0

要獲得索引值,你必須編譯和執行的表達 - 這是昂貴,但它可以使用ExpressionStringBuilder修改版本來完成。請注意,我添加了一個參數。當它設置爲false時,輸出結果將類似於Model.CargoTasks[_.j].IsSet

請注意,此示例訪問者不完整(即,它不支持各種表達式)。你可以使用code in GitHub來補充它。

public static string ToMemberAccess<TResult>(Expression<Func<TResult>> expression, bool compileConstants = false) 
{ 
    var builder = new ExpressionStringBuilder(compileConstants); 
    builder.Visit(expression); 
    return builder.ToString(); 
} 

internal class ExpressionStringBuilder : ExpressionVisitor 
{ 
    private readonly bool _compileConstants; 
    private readonly StringBuilder _out; 

    public ExpressionStringBuilder(bool compileConstants) 
    { 
     _compileConstants = compileConstants; 
     _out = new StringBuilder(); 
    } 

    protected override Expression VisitConstant(ConstantExpression node) 
    { 
     if (node.Value != null) 
     { 
      string text = node.Value.ToString(); 
      if (node.Value is string) 
      { 
       Out("\""); 
       Out(text); 
       Out("\""); 
      } 
      else if (text == node.Value.GetType().ToString()) 
      { 
       Out('_'); 
      } 
      else 
      { 
       Out(text); 
      } 
     } 
     else 
     { 
      Out("null"); 
     } 
     return node; 
    } 

    protected override Expression VisitMethodCall(MethodCallExpression node) 
    { 
     int num = 0; 
     Expression expression = node.Object; 
     if (Attribute.GetCustomAttribute(node.Method, typeof(ExtensionAttribute)) != null) 
     { 
      num = 1; 
      expression = node.Arguments[0]; 
     } 
     var name = node.Method.Name; 
     var isIndexer = name == "get_Item"; 
     if (expression != null) 
     { 
      Visit(expression); 
      if (!isIndexer) 
      { 
       Out('.'); 
      } 
     } 
     if (isIndexer) 
      Out('['); 
     else 
     { 
      Out(name); 
      Out('('); 
     } 
     int i = num; 
     int count = node.Arguments.Count; 
     while (i < count) 
     { 
      if (i > num) 
      { 
       Out(", "); 
      } 
      VisitArgument(node.Arguments[i]); 
      i++; 
     } 
     Out(isIndexer ? ']' : ')'); 
     return node; 
    } 

    protected override Expression VisitIndex(IndexExpression node) 
    { 
     if (node.Object != null) 
     { 
      Visit(node.Object); 
     } 
     else 
     { 
      Out(node.Indexer.DeclaringType.Name); 
     } 
     if (node.Indexer != null) 
     { 
      Out("."); 
      Out(node.Indexer.Name); 
     } 

     Out('['); 
     for (var index = 0; index < node.Arguments.Count; index++) 
     { 
      if (index > 0) 
      { 
       Out(", "); 
      } 
      var expression = node.Arguments[index]; 
      VisitArgument(expression); 
     } 
     Out(']'); 
     return node; 
    } 

    protected override Expression VisitLambda<T>(Expression<T> node) 
    { 
     Visit(node.Body); 
     return node; 
    } 

    protected override Expression VisitMember(MemberExpression node) 
    { 
     OutMember(node.Expression, node.Member); 
     return node; 
    } 

    public override string ToString() 
    { 
     return _out.ToString(); 
    } 

    private void VisitArgument(Expression expression) 
    { 
     if (_compileConstants) 
     { 
      // TODO: possibly check the expression is not dependent on parameters 
      var value = Expression.Lambda(expression).Compile().DynamicInvoke(); 
      Out(value + string.Empty); 

     } 
     else 
     { 
      VisitArgument(expression); 
     } 
    } 

    private void OutMember(Expression instance, MemberInfo member) 
    { 
     if (instance != null) 
     { 
      Visit(instance); 
      if (_out.Length > 0) 
       Out('.'); 
      Out(member.Name); 
      return; 
     } 
     Out(member.DeclaringType.Name + "." + member.Name); 
    } 

    private void Out(char c) 
    { 
     _out.Append(c); 
    } 

    private void Out(string s) 
    { 
     _out.Append(s); 
    } 
} 
+0

非常感謝您的迴應! 這很好。 – MitchellNZ

相關問題