2012-06-08 4 views
10

कोई भी ऐसे कोड के बारे में जानता है जो DebuggerDisplayAttribute पार्स को डुप्लिकेट करता है और परिणामस्वरूप स्ट्रिंग को एकत्र करता है?कोई भी कोड जो डुप्लिकेट करता है कि कैसे DebuggerDisplayAttribute परिणामी स्ट्रिंग उत्पन्न करता है?

मैं एक कस्टम विशेषता बनाना चाहता हूं जो लगभग नमूना चीज करता है। "जब ब्रेकपॉइंट मारा जाता है ..." के समान है जहां आप "{variable}" के रूप में घुंघराले ब्रेसिज़ के भीतर एक चर का उपयोग कर सकते हैं।

मैं पहले से ही "{नाम}" जैसे साधारण मामलों को संभालता हूं, लेकिन "{Foo.Name}" जैसे कुछ को अतिरिक्त प्रतिबिंब कोड की आवश्यकता होती है जिसके लिए मुझे सहायता चाहिए।

असल में, मैं DebuggerDisplayAttribute दस्तावेज़ में परिभाषित नियमों का उपयोग करके एक स्ट्रिंग को पार्स करना चाहता हूं। वर्तमान में, मैं पार्स और हल कर सकता हूं "मैं {GetName()} हूं"। मुझे "फू का नाम: {Foo.Name}"

+0

आप विजुअल स्टूडियो के व्यवहार को बदलने का प्रयास कर रहे हैं। इसलिए जब आप आसानी से अपनी खुद की विशेषता बना सकते हैं, तो आपको इसे पहचानने और रिपोर्ट करने के लिए विजुअल स्टूडियो का विस्तार करना होगा। फिर भी, मुझे यकीन नहीं है कि क्या आप उस डिग्री में व्यवहार बदल सकते हैं। यदि यह संभव है, तो यह शुरू करने का स्थान होगा: http://msdn.microsoft.com/en-us/library/bb161946.aspx – JDB

+0

@ साइबोर्गक्स 37; नहीं। मैं केवल कार्यक्षमता को डुप्लिकेट करना चाहता हूं। स्ट्रिंग को पार्स करने और प्रतिबिंब के माध्यम से मूल्यों को इकट्ठा करने के लिए। – AMissico

+0

दुर्भाग्य से मुझे नहीं लगता कि ऐसा करने का कोई तरीका है, इस संबंधित प्रश्न को देखें: http://stackoverflow.com/questions/2793965/does-there-exists-a-method-to-render-an-object-using -debuggerdisplayattribute फ्रेमवर्क में प्रकट इस कार्यक्षमता को देखना अच्छा लगेगा। शायद आप इसे कनेक्ट करने का अनुरोध कर सकते हैं - अगर ऐसा है तो मैं इसके लिए वोट दूंगा! – Joe

उत्तर

2

कुछ ऐसा करने में सहायता चाहिए, मुझे लगता है कि यह आपके स्वयं के (टीम) उपयोग के लिए है। मैंने व्यक्तिगत रूप से यह कोशिश नहीं की है, लेकिन क्या आपने here को डिबगर डिस्प्ले विशेषता को अनुकूलित करने के तरीके के बारे में स्पष्टीकरण देखा है?

+0

मुझे पता है कि विशेषता कैसे काम करती है। जैसा कि मैंने उल्लेख किया है, मैं मुख्य वस्तु पर विधियों या गुणों को संभाल सकता हूं। यह मुख्य वस्तु के गुणों पर गुण और विधियां हैं जिनके लिए मुझे अतिरिक्त सहायता चाहिए। – AMissico

+0

मैं कुछ और सुझाव नहीं दे रहा था, लेकिन मैंने सोचा कि आपको यह एहसास नहीं हुआ होगा कि आप वास्तव में (स्पष्ट रूप से) deexgerDisplayAttribute को autoexp.cs संपादित करके विस्तारित कर सकते हैं। आप अपनी पोस्ट में समझा नहीं रहे हैं कि आप किस कार्यक्षमता की तलाश में हैं। –

+0

आह, अद्यतन प्रश्न। – AMissico

5

उम्मीद है कि यह कोड सभी फिट बैठता है ... मैंने माइक्रोसॉफ्ट रोज़लिन और इसकी सी # स्क्रिप्टिंग क्षमता को "कोड" को सी # कोड के रूप में विशेषता मान में चलाने के लिए उपयोग करने की कोशिश कर रहे एक गैर-प्रतिबिंब संस्करण बनाया है।

इस कोड का उपयोग करने के लिए, एक नया सी # प्रोजेक्ट बनाएं, और रोज़लिन के संदर्भ को जोड़ने के लिए NuGet का उपयोग करें।

पहले कक्षाएं जिन्हें मैं परीक्षण करने के लिए उपयोग कर रहा हूं, बस आप मेरे द्वारा किए गए गुणों को देख सकते हैं।

using System.Diagnostics; 

namespace DebuggerDisplayStrings 
{ 
    [DebuggerDisplay("The Value Is {StringProp}.")] 
    public class SomeClass 
    { 
     public string StringProp { get; set; } 
    } 

    [DebuggerDisplay("The Value Is {Foo.StringProp}.")] 
    public class SomeClass2 
    { 
     public SomeClass Foo { get; set; } 
    } 

    [DebuggerDisplay("The Value Is {Seven() - 6}.")] 
    public class SomeClass3 
    { 
     public int Seven() 
     { 
      return 7; 
     } 
    } 
} 

अब परीक्षण (हाँ इन सभी पास):

using Microsoft.VisualStudio.TestTools.UnitTesting; 

namespace DebuggerDisplayStrings 
{ 
    [TestClass] 
    public class DebuggerDisplayReaderTests 
    { 
     [TestMethod] 
     public void CanReadStringProperty() 
     { 
      var target = new SomeClass {StringProp = "Foo"}; 
      var reader = new DebuggerDisplayReader(); 
      Assert.AreEqual("The Value Is Foo.", reader.Read(target)); 
     } 

     [TestMethod] 
     public void CanReadPropertyOfProperty() 
     { 
      var target = new SomeClass2 {Foo = new SomeClass {StringProp = "Foo"}}; 
      var reader = new DebuggerDisplayReader(); 
      Assert.AreEqual("The Value Is Foo.", reader.Read(target)); 
     } 

     [TestMethod] 
     public void CanReadMethodResultAndDoMath() 
     { 
      var target = new SomeClass3(); 
      var reader = new DebuggerDisplayReader(); 
      Assert.AreEqual("The Value Is 1.", reader.Read(target)); 
     } 
    } 
} 

अंत में, असली माल:

using System.Collections.Generic; 
using System.Diagnostics; 
using System.Globalization; 
using System.Text.RegularExpressions; 
using Roslyn.Scripting.CSharp; 

namespace DebuggerDisplayStrings 
{ 
    public class DebuggerDisplayReader 
    { 
     // Get the fully evaluated string representation of the DebuggerDisplayAttribute's value. 
     public string Read(object target) 
     { 
      var debuggerDisplayFormat = GetDebuggerDisplayFormat(target); 
      if(string.IsNullOrWhiteSpace(debuggerDisplayFormat)) 
       return target.ToString(); 
      return EvaluateDebuggerDisplayFormat(debuggerDisplayFormat, target); 
     } 

     // Gets the string off the attribute on the target class, or returns null if attribute not found. 
     private static string GetDebuggerDisplayFormat(object target) 
     { 
      var attributes = target.GetType().GetCustomAttributes(typeof(DebuggerDisplayAttribute), false); 
      return attributes.Length > 0 ? ((DebuggerDisplayAttribute)attributes[0]).Value : null; 
     } 

     // Executes each bracketed portion of the format string using Roslyn, 
     // and puts the resulting value back into the final output string. 
     private string EvaluateDebuggerDisplayFormat(string format, object target) 
     { 
      var scriptingEngine = new ScriptEngine(new[] { GetType().Assembly }); 
      var formatInfo = ExtractFormatInfoFromFormatString(format); 
      var replacements = new List<object>(formatInfo.FormatReplacements.Length); 
      foreach (var codePart in formatInfo.FormatReplacements) 
      { 
       var result = scriptingEngine.Execute(codePart, target); 
       replacements.Add((result ?? "").ToString()); 
      } 
      return string.Format(formatInfo.FormatString, replacements.ToArray()); 
     } 

     // Parse the format string from the attribute into its bracketed parts. 
     // Prepares the string for string.Format() replacement. 
     private static DebuggerDisplayFormatInfo ExtractFormatInfoFromFormatString(string format) 
     { 
      var result = new DebuggerDisplayFormatInfo(); 
      var regex = new Regex(@"\{(.*)\}"); 
      var matches = regex.Matches(format); 
      result.FormatReplacements = new string[matches.Count]; 
      for (var i = matches.Count - 1; i >= 0; i--) 
      { 
       var match = matches[i]; 
       result.FormatReplacements[i] = match.Groups[1].Value; 
       format = format.Remove(match.Index + 1, match.Length - 2).Insert(match.Index+1, i.ToString(CultureInfo.InvariantCulture)); 
      } 
      result.FormatString = format; 
      return result; 
     } 
    } 

    internal class DebuggerDisplayFormatInfo 
    { 
     public string FormatString { get; set; } 
     public string[] FormatReplacements { get; set; } 
    } 
} 

उम्मीद है कि है कि आप में मदद करता है बाहर। यह केवल डेढ़ घंटे का काम था, इसलिए यूनिट परीक्षण किसी भी माध्यम से पूरा नहीं होता है, और मुझे यकीन है कि वहां कहीं भी बग हैं, लेकिन यह एक ठोस शुरुआत होनी चाहिए, अगर आप ठीक हैं Roslyn दृष्टिकोण।

+0

http://blogs.msdn.com/b/visualstudio/archive/2011/10/19/introducing-the-microsoft-roslyn-ctp.aspx – AMissico

+0

http://en.wikipedia.org/wiki/Microsoft_Roslyn – AMissico

+0

http : //www.microsoft.com/en-us/download/details.aspx? id = 27746 – AMissico

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

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