Esperemos que este código encaje ... Hice una versión no reflectante de lo que está tratando de hacer, usando Microsoft Roslyn y su capacidad de C# Scripting para ejecutar el "código" en el valor del atributo como código C#.
Para usar este código, cree un nuevo proyecto de C# y use NuGet para agregar una referencia a Roslyn.
Primero las clases que estoy usando para probar, solo para que pueda ver los atributos que probé.
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;
}
}
}
Ahora las pruebas (sí todos estos pases):
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));
}
}
}
bienes Por último, las reales:
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; }
}
}
suerte que le ayuda a cabo. Solo fue una hora y media de trabajo, por lo que las pruebas unitarias no están completas de ninguna manera, y estoy seguro de que hay errores en alguna parte, pero debería ser un comienzo sólido, si estás de acuerdo con el Roslyn se acerca.
Está intentando cambiar el comportamiento de Visual Studio. Entonces, si bien podría crear fácilmente su propio atributo, necesitaría extender Visual Studio para reconocerlo e informarlo. Incluso entonces, no estoy seguro de si puedes cambiar el comportamiento hasta ese grado. Si es posible, este sería el lugar para comenzar: http://msdn.microsoft.com/en-us/library/bb161946.aspx – JDB
@ Cyborgx37; No. Quiero duplicar la funcionalidad solamente. Para analizar la cadena y reunir los valores a través de la reflexión. – AMissico
Lamentablemente, no creo que haya ninguna forma de hacerlo, consulte esta pregunta relacionada: http://stackoverflow.com/questions/2793965/does-there-exists-a-method-to-render-un-object-using -debuggerdisplayattribute Sería bueno ver esta funcionalidad expuesta en el Framework. Tal vez podrías solicitarlo conéctate, ¡si es así lo votaré! – Joe