Нет лучшего способа, чем код, который вы уже написали, если вы действительно настроены на все свойства и поля. Вы можете написать метод расширения и объединить его в пространство имен System, таким образом оно появится в каждом экземпляре любого типа; Я хотел бы также серьезно рассмотреть вопрос об использовании StringBuilder
, AppendLine
и string.Format
:
namespace System
{
public static class MyExtensions
{
public static string Report<T>(this T instance)
{
StringBuilder sb = new StringBuilder();
foreach (PropertyInfo prop in typeof(T).GetProperties())
{
sb.AppendLine(
string.Format("{0} = {1}", prop.Name, prop.GetValue(si, null));
}
foreach (FieldInfo prop in typeof(T).GetFields())
{
sb.AppendLine(
string.Format("{0} = {1}", prop.Name, prop.GetValue(si, null));
}
return sb.ToString();
}
}
}
После того, как вы написали это, вы можете просто сделать:
var instance = new ServerInfo();
var report = instance.Report();
Проблема с этим состоит в том, что он не обрабатывает ситуация, когда наилучшим представлением типа на самом деле является только вызов ToString, например int
или string
(строка особенно, поскольку этот код просто выводит элемент Length
).
Вы упоминаете DataGrid WPF - это стоит отметить, что это не использует отражения напрямую, вместо этого он использует System.ComponentModel.TypeDescriptor
класса - который является расширяемым и использует механизм TypeConverter
для поддержки преобразования в/из строк (намного лучше, чем просто полагаться на ToString
).
Однако он не содержит полей в метаданных, которые он производит; которые вы явно хотите.
В качестве заключительного замечания я бы сказал, что такого рода вещи не должны использоваться много в программах; потому что очень редко этот уровень детализации имеет значение.Тогда возникает вопрос, насколько глубоко ваш отчет должен идти; для каждого члена, если вы на самом деле не используете снова Report
(в этом случае вам нужно либо опоздать на поздний срок, либо просто написать его вместо object
)? Но тогда у вас есть неприятный код для проверки типов, которые должны быть сведены в или только ToString
'd. И если вы начнете делать это, вам также необходимо позаботиться о том, чтобы не переписываться через перекрестные ссылки; в противном случае метод отчета может просто заблокировать ваше приложение.
Я хотел бы предложить вместо этого интерфейс лучше:
public interface IReportable
{
void Report(StringBuilder target);
}
Реализация интерфейс, то ограничивается только типами, которые вам действительно нужны, чтобы сообщить о; и вы можете использовать метод расширения выше или один из них как реализацию по умолчанию для большинства ваших типов. Тем не менее, важно, что тип может предоставить свои собственные, если это необходимо.
Доступный код [здесь] (http://stackoverflow.com/a/6745255/870604) действительно прост, почему бы вам не использовать его? – ken2k
Что вам не понравилось в ответе? –
Замените что-нибудь вроде чего? –