Umarız bu kod hepsi uyuyor ... Microsoft Roslyn ve C# Scripting özelliğini kullanarak C# kodu olarak öznitelik değerindeki "kodu" çalıştırma yeteneğini kullanarak, yapmaya çalıştığınız şeyin yansımayan bir sürümünü yaptım.
Bu kodu kullanmak için, yeni bir C# projesi yapın ve Roslyn'e başvuru eklemek için NuGet'i kullanın.
İlk olarak test etmek için kullanıyorum sınıfları, denediğim öznitelikleri görebilirsiniz.
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;
}
}
}
Şimdi testleri (evet bunların hepsi pas):
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));
}
}
}
Son olarak, gerçek eşya: size yardımcı oluyor
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; }
}
}
Umarım. Sadece bir buçuk saatlik bir işti, bu yüzden birim testi herhangi bir yolla tamamlanmadı, ve eminim ki orada bir yerde hatalar var, ama sağlam bir başlangıç olmalı. Roslyn yaklaşımı.
Visual Studio'nun davranışını değiştirmeye çalışıyorsunuz. Böylece kendi özniteliğinizi kolayca oluşturabiliyor olsanız da, bunu tanımak ve raporlamak için Visual Studio'yu genişletmeniz gerekir. O zaman bile, davranışı o dereceye kadar değiştirip değiştiremeyeceğinizden emin değilim. Mümkünse, burası başlangıç noktası olacaktır: http://msdn.microsoft.com/en-us/library/bb161946.aspx – JDB
@ Cyborgx37; Hayır. Sadece işlevselliği çoğaltmak istiyorum. Dizeyi ayrıştırmak ve değerleri yansıtma yoluyla toplamak. – AMissico
Maalesef bunu yapmanın bir yolu olduğunu düşünmüyorum, şu soruya bakın: http://stackoverflow.com/questions/2793965/does-there-exists-a-method-to-render-an-object-using -debuggerdisplayattribute Bu işlevselliği Framework'de görmek güzel olurdu. Belki de bağlantı üzerinden talep edebilirsiniz - eğer öyleyse bunun için oy kullanacağım! – Joe