using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Diagnostics;
using System.Timers;
using System.Threading;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Configuration;
using System.Reflection;
namespace DiagnosticExplorer
{
public static partial class DiagnosticManager
{
private static List<RegisteredObject> RegisteredObjects { get; set; }
private static Dictionary<string, List<PropertyGetter>> typeHash
= new Dictionary<string, List<PropertyGetter>>();
static DiagnosticManager()
{
RegisteredObjects = new List<RegisteredObject>();
}
public static void Register(object o, string bagName, string bagCategory)
{
lock (RegisteredObjects)
{
RegisteredObject existing = RegisteredObjects.Find(
ro => ReferenceEquals(ro.Object, o));
if (existing == null)
{
bagName += GetUniqueBagNameExtension(bagName);
RegisteredObjects.Add(new RegisteredObject(o, bagName, bagCategory));
}
}
}
public static void Unregister(object obj)
{
lock (RegisteredObjects)
{
RegisteredObject existing = RegisteredObjects.Find(
ro => ReferenceEquals(ro.Object, obj));
if (existing != null)
RegisteredObjects.Remove(existing);
}
}
public static IEnumerable<PropertyBag> GetRegisteredProperties()
{
RegisteredObject[] objects = null;
lock (RegisteredObjects)
objects = RegisteredObjects.ToArray();
foreach (RegisteredObject regObj in objects)
{
object obj = regObj.Object;
if (obj == null)
{
lock (RegisteredObjects)
RegisteredObjects.Remove(regObj);
}
else
{
yield return ObjectToPropertyBag(obj, regObj.BagName, regObj.BagCategory);
}
}
}
private static string GetUniqueBagNameExtension(string name)
{
if (name == null)
return null;
if (!BagNameExists(name))
return null;
for (int i = 2; ; i++)
{
string extension = string.Format(" {0}", i);
string newName = string.Format("{0}{1}", name, extension);
if (!BagNameExists(newName))
return extension;
}
}
private static bool BagNameExists(string name)
{
lock (RegisteredObjects)
{
RegisteredObject regObj = RegisteredObjects.Find(
ro => string.Compare(name, ro.BagName, true) == 0);
return regObj != null;
}
}
internal static PropertyBag ObjectToPropertyBag(object obj, string bagName, string bagCategory)
{
PropertyBag bag = new PropertyBag();
bag.Name = bagName;
bag.Category = bagCategory;
List<PropertyGetter> valueGetters = GetPropertyGetters(obj);
foreach (PropertyGetter getter in valueGetters)
bag.Properties.AddRange(getter.GetProperties(obj));
return bag;
}
public const BindingFlags PublicInstancePropertyFlags = BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Instance;
public const BindingFlags PublicStaticPropertyFlags = BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Static;
internal static List<PropertyGetter> GetPropertyGetters(object obj, string categoryPrepend)
{
List<PropertyGetter> getters = GetPropertyGetters(obj);
List<PropertyGetter> newGetters = new List<PropertyGetter>();
foreach (PropertyGetter g in getters)
newGetters.Add(new CategoryPrependPropertyGetter(g, categoryPrepend));
return newGetters;
}
internal static List<PropertyGetter> GetPropertyGetters(object obj)
{
if (obj == null) return new List<PropertyGetter>();
Type type = obj.GetType();
string typeKey = type.AssemblyQualifiedName;
if (obj is Type)
{
type = (Type)obj;
typeKey = "Static: " + type.AssemblyQualifiedName;
}
List<PropertyGetter> propertyList;
if (!typeHash.TryGetValue(typeKey, out propertyList))
{
propertyList = new List<PropertyGetter>();
IEnumerable<PropertyInfo> properties = obj is Type ? GetStaticProperties(type) : GetInstanceProperties(type, null);
foreach (PropertyInfo info in properties)
{
Type underlying = GetUnderlyingType(info.PropertyType);
PropertyAttribute propAttr = GetAttribute<PropertyAttribute>(info);
CollectionPropertyAttribute colPropAttr = propAttr as CollectionPropertyAttribute;
ExtendedPropertyAttribute extPropAttr = propAttr as ExtendedPropertyAttribute;
if (colPropAttr != null)
{
propertyList.Add(new CollectionGetter(info, colPropAttr));
}
else if (extPropAttr != null)
{
propertyList.Add(new ExtendedPropertyGetter(info, extPropAttr));
}
else if (info.PropertyType == typeof(RateCounter))
{
RatePropertyAttribute rateAttr = propAttr as RatePropertyAttribute;
propertyList.Add(new RateGetter(info, rateAttr));
}
else if (underlying == typeof(DateTime))
{
DatePropertyAttribute dateAttr = propAttr as DatePropertyAttribute;
propertyList.Add(new DateGetter(info, dateAttr));
}
else
{
propertyList.Add(new PropertyGetter(info));
}
}
typeHash[typeKey] = propertyList;
}
return propertyList;
}
private static IEnumerable<PropertyInfo> GetInstanceProperties(Type type, DiagnosticClassAttribute inheritedAttr)
{
if (type != typeof (object))
{
DiagnosticClassAttribute diagAttr = GetAttribute<DiagnosticClassAttribute>(type, false);
if (inheritedAttr == null || !inheritedAttr.DeclaringTypeOnly || diagAttr != null)
{
foreach (PropertyInfo propInfo in type.GetProperties(PublicInstancePropertyFlags | BindingFlags.DeclaredOnly))
if (ShouldIncludeProperty(diagAttr ?? inheritedAttr, type, propInfo))
yield return propInfo;
}
foreach (PropertyInfo propInfo in GetInstanceProperties(type.BaseType, diagAttr ?? inheritedAttr))
yield return propInfo;
}
}
private static IEnumerable<PropertyInfo> GetStaticProperties(Type type)
{
DiagnosticClassAttribute diagAttr = GetAttribute<DiagnosticClassAttribute>(type, false);
return type
.GetProperties(PublicStaticPropertyFlags)
.Where(propInfo => ShouldIncludeProperty(diagAttr, type, propInfo));
}
private static bool ShouldIncludeProperty(DiagnosticClassAttribute diagAttr, Type declaringType, PropertyInfo info)
{
if (info.PropertyType == typeof(EventSink)) return false;
if (info.DeclaringType.IsAssignableFrom(typeof(ApplicationSettingsBase)))
return GetAttribute<SettingAttribute>(info) != null;
bool attributedOnly = diagAttr != null && diagAttr.AttributedPropertiesOnly;
BrowsableAttribute browseAttr = GetAttribute<BrowsableAttribute>(info);
PropertyAttribute propAttr = GetAttribute<PropertyAttribute>(info);
if (propAttr != null)
return !propAttr.Ignore;
if (browseAttr != null && !browseAttr.Browsable)
return false;
if (attributedOnly)
return browseAttr != null;
return true;
}
public static Type GetUnderlyingType(Type t)
{
if (t == null) throw new ArgumentNullException("t");
if (!t.IsGenericType) return t;
if (t.GetGenericTypeDefinition() != typeof(Nullable<>)) return t;
return t.GetGenericArguments()[0];
}
private static T GetAttribute<T>(PropertyInfo info) where T : Attribute
{
object[] attrs = info.GetCustomAttributes(typeof(T), false);
if (attrs.Length == 0)
return null;
return attrs[0] as T;
}
private static T GetAttribute<T>(Type info, bool inherit) where T : Attribute
{
object[] attrs = info.GetCustomAttributes(typeof(T), inherit);
if (attrs.Length == 0)
return null;
return attrs[0] as T;
}
}
}