2012-09-16 13 views
7

प्रश्न: मैं विरासत कक्षाओं के लिए डीबगर प्रकार प्रॉक्सी के निर्माण को सरल बनाने के लिए एक तरीका ढूंढ रहा हूं। इसलिए, जब किसी वर्ग से प्राप्त होने वाली कक्षा को डीबग करते समय, मुझे दोनों तरफ से गुणों को देखना चाहिए: बेस क्लास के मूल गुण, साथ ही मूल वर्ग के नए गुण।मैं अपने डीबगर टाइपप्रोक्सी लक्ष्य वर्ग बेस प्रॉक्सी से कैसे प्राप्त कर सकता हूं?

यहाँ मैं अब तक की कोशिश की है है:

  1. NewA के प्रकार, प्रॉक्सी A की कि से विरासत। गुण साइड-साइड नहीं दिखाते हैं; बेस गुण Base के तहत छतरी [एसआईसी] हैं। *****
  2. NewA में एक A संपत्ति है कि सिर्फ वर्तमान NewAA को डाले, [DebuggerBrowsable(RootHidden)] साथ सहित: दृश्य स्टूडियो लटकी हुई है :(

मुझे पता है कि मैं सिर्फ आधार के लिए गुण जोड़ सकते हैं NewA के प्रॉक्सी में वर्ग है, लेकिन मैं इस से बचने के लिए कोशिश कर रहा हूँ यह कई गुणों के साथ कक्षाओं के लिए बहुत ज्यादा काम है


स्पष्टीकरण:।।

मैं अपने कुछ वर्गों पर DebuggerTypeProxy विशेषता का उपयोग कर रहा हूं, इसलिए मैं डीबगिंग के दौरान ब्राउज़ करते समय कक्षा को कैसे देखता हूं इसे नियंत्रित कर सकता हूं। उदाहरण के लिए:

enter image description here

... इसलिए मैं एक DebuggerTypeProxy का उपयोग समर्थन क्षेत्र को छिपाने के लिए:

[DebuggerTypeProxy(typeof(AProxy))] 
public class A { 
    // ... 

    internal class AProxy { 
     A _a; 
     AProxy (A a){ 
      _a = a; 
     } 

     public String SomeField { 
      get {return _a.SomeField;} 
     } 
    } 
} 

public class A { 
    private String _someField; 

    public String SomeField { 
     get {return _someField;} 
    } 
} 

डिफ़ॉल्ट रूप से, टूलटिप जानकारी डिबगिंग रूप में दिखाता है ... सभी दुनिया के साथ सही हैं:

enter image description here


अब, मैं एक वर्ग है कि ए

public class NewA : A { 
    private String _anotherField; 
    public String AnotherField { 
     get {return _anotherField;} 
    } 
} 

दुर्भाग्य से विरासत बनाने के लिए, जब इस वर्ग डीबगिंग, विजुअल स्टूडियो आधार प्रकार, प्रॉक्सी (A से) का उपयोग करता है। इसका मतलब यह है कि हम आधार SomeField संपत्ति देख सकते हैं, लेकिन हमारे नए AnotherField संपत्ति छिपा हुआ है (जब तक आप Raw View का विस्तार, निश्चित रूप से):

enter image description here

AnotherField दिखाने में A परिणाम के आधार से प्रकार प्रॉक्सी निकाला जा रहा है, लेकिन नहीं SomeField


* असफल प्रयास # 1

/// <summary> 
/// The base class 
/// </summary> 
[DebuggerTypeProxy(typeof(AProxy))] 
public class A { 
    private String _someField; 

    public String SomeField { 
     get { return _someField; } 
    } 

    protected class AProxy { 
     A _a; 
     protected AProxy(A a) { 
      _a = a; 
     } 

     String SomeField { 
      get { return _a.SomeField; } 
     } 
    } 

} 

/// <summary> 
/// Parent class 
/// </summary> 
[DebuggerTypeProxy(typeof(NewAProxy))] 
public class NewA : A { 
    private String _anotherField; 
    public String AnotherField { 
     get { return _anotherField; } 
    } 

    // Inherit base type proxy, in an effort to display base properties 
    // side-by-side with AnotherField: Doesn't work. 
    protected class NewAProxy : A.AProxy { 
     NewA _newA; 
     protected NewAProxy(NewA newA) 
      : base(newA) { 
      _newA = newA; 
     } 

     public String AnotherField { 
      get { return _newA.AnotherField; } 
     } 
    } 
} 

परिणाम:

enter image description here

फिर भी काम नहीं करता। आधार गुणों को नई संपत्तियों के साथ-साथ नहीं रखा जाता है।

उत्तर

5

खोज और टिंकरिंग के घंटों के बाद, मुझे समाधान मिला - और उस पर एक सुंदर - from Jared Par's blog। वह एक प्रकार की प्रॉक्सी बनाता है जो सभी सदस्यों को एक सूची में घुलनाने के लिए प्रतिबिंब का उपयोग करता है। कुछ अतिरिक्त DebuggerDisplay जादू इसे बनाता है ताकि आप ध्यान न दें।

// http://blogs.msdn.com/b/jaredpar/archive/2010/02/19/flattening-class-hierarchies-when-debugging-c.aspx 
// by Jared Par 
internal sealed class FlattenHierarchyProxy { 

    [DebuggerDisplay("{Value}", Name = "{Name,nq}", Type = "{Type.ToString(),nq}")] 
    internal struct Member { 
     internal string Name; 
     internal object Value; 
     internal Type Type; 
     internal Member(string name, object value, Type type) { 
      Name = name; 
      Value = value; 
      Type = type; 
     } 
    } 

    [DebuggerBrowsable(DebuggerBrowsableState.Never)] 
    private readonly object _target; 
    [DebuggerBrowsable(DebuggerBrowsableState.Never)] 
    private Member[] _memberList; 

    [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] 
    internal Member[] Items { 
     get { 
      if (_memberList == null) { 
       _memberList = BuildMemberList().ToArray(); 
      } 
      return _memberList; 
     } 
    } 

    public FlattenHierarchyProxy(object target) { 
     _target = target; 
    } 

    private List<Member> BuildMemberList() { 
     var list = new List<Member>(); 
     if (_target == null) { 
      return list; 
     } 

     var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; 
     var type = _target.GetType(); 
     foreach (var field in type.GetFields(flags)) { 
      var value = field.GetValue(_target); 
      list.Add(new Member(field.Name, value, field.FieldType)); 
     } 

     foreach (var prop in type.GetProperties(flags)) { 
      object value = null; 
      try { 
       value = prop.GetValue(_target, null); 
      } 
      catch (Exception ex) { 
       value = ex; 
      } 
      list.Add(new Member(prop.Name, value, prop.PropertyType)); 
     } 

     return list; 
    } 
} 


संशोधन

मैं इसे और अधिक मेरे लिए उपयोगी बनाने के लिए वर्ग के लिए तीन छोटे सुधार किए हैं।

सबसे पहले, मैं चाहता था कि सदस्य नाम से क्रमबद्ध हों। ऐसा करने के लिए, करने के लिए अंतिम पंक्ति को बदलने:

return list.OrderBy(m => m.Name).ToList(); 

दूसरा, Member struct में, मैं कुछ विशेषताएं जोड़ी ताकि केवल मूल्य जब आप एक संदर्भ वर्ग का विस्तार आएगा:

[DebuggerBrowsable(DebuggerBrowsableState.Never)] 
internal string Name; 
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] 
internal object Value; 
[DebuggerBrowsable(DebuggerBrowsableState.Never)] 
internal Type Type; 

तीसरा , डिफ़ॉल्ट झंडे BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance का अर्थ है कि [DebuggerBrowsable(DebuggerBrowsableState.Never)] चिह्नित सदस्यों को भी दिखाया जाएगा। ऐसा होने से रोकने के लिए, इस लाइन के बाद:

foreach (var field in type.GetFields(flags)) { 

इस जोड़ें:

// Respect DebuggerBrowsableAttributes 
var debuggerBrowsableAtts = field.GetCustomAttributes(typeof(DebuggerBrowsableAttribute), true); 
if (debuggerBrowsableAtts.Count() == 1) { 
    var att = debuggerBrowsableAtts[0] as DebuggerBrowsableAttribute; 
    if (att.State == DebuggerBrowsableState.Never) { 
     continue; 
    } 
} 

अब DebuggerBrowsable(DebuggerBrowsableState.Never) क्षेत्रों के लिए मान्य होंगी। आप उस कोड को फ़ोरैच लूप भी जोड़ सकते हैं जो गुणों को संभालता है, इसे गुणों के लिए भी सम्मानित किया जाता है।

+0

आप गुणों के लिए डीबगर ब्रोसेबल एट्रिब्यूट भी सक्षम कर सकते हैं। –

संबंधित मुद्दे

 संबंधित मुद्दे