using System;
using System.Collections;
using System.Diagnostics;
using System.Text;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.IO;
using System.Runtime.Serialization;
using System.ComponentModel;
using Sleis.Validation.Spring;
using Sleis.Models;
namespace Sleis.Utility
{
[AttributeUsage(AttributeTargets.Property)]
public class ToStringQualifierAttribute : Attribute
{
private bool _ignore;
private bool _collectionCountOnly;
public ToStringQualifierAttribute() { }
///
/// Ignore this property in the string output
///
public bool Ignore
{
get { return _ignore; }
set { _ignore = value; }
}
///
/// Only output ICollection.Count, not any of the elements in the string output
///
public bool CollectionCountOnly
{
get { return _collectionCountOnly; }
set { _collectionCountOnly = value; }
}
}
///
/// Basic helper functions for dealing with reflection.
///
public static class ReflectionUtility
{
public delegate bool ForEachProperty(PropertyInfo propertyInfo);
public static void ProcessPublicInstanceProperties(object obj, ForEachProperty forEach)
{
if (obj == null)
{
return;
}
ProcessPublicInstanceProperties(obj.GetType(), forEach);
}
public static void ProcessPublicInstanceProperties(Type type, ForEachProperty forEach)
{
List propertyList = new List();
Type curType = type;
do
{
PropertyInfo[] properties = curType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
propertyList.AddRange(properties);
curType = curType.BaseType;
} while (curType != null);
foreach (PropertyInfo property in propertyList)
{
if (!forEach(property))
{
return;
}
}
//PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
//foreach (PropertyInfo property in properties)
//{
// if (!forEach(property))
// {
// return;
// }
//}
}
///
/// This works around an issue in .NET where Type.GetFields(BindingFlags.Public | BindingFlags.NonPublic |
/// BindingFlags.Instance) does not return private, inherited fields!
///
public static IList GetAllPublicAndPrivateInstanceFields(Type inType)
{
List fieldInfoList = new List();
Type curType = inType;
do
{
FieldInfo[] fieldInfoArray = curType.GetFields(BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.DeclaredOnly);
fieldInfoList.AddRange(fieldInfoArray);
curType = curType.BaseType;
} while (curType != null);
return fieldInfoList;
}
///
/// This works around an issue in .NET where Type.GetFields(BindingFlags.Public | BindingFlags.NonPublic |
/// BindingFlags.Instance) does not return private, inherited fields!
///
public static object GetPublicOrPrivatePropertyValue(object obj, string propertyName, bool declaredOnly)
{
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
if (declaredOnly)
{
flags |= BindingFlags.DeclaredOnly;
}
PropertyInfo propInfo = obj.GetType().GetProperty(propertyName, flags);
if (propInfo == null)
{
throw new ArgumentException(string.Format("The property {0} was not found for the object {1}",
propertyName, obj.GetType().FullName));
}
return propInfo.GetValue(obj, null);
}
///
/// This works around an issue in .NET where Type.GetFields(BindingFlags.Public | BindingFlags.NonPublic |
/// BindingFlags.Instance) does not return private, inherited fields!
///
public static FieldInfo GetFieldByName(Type inType, string fieldName)
{
List fieldInfoList = new List();
Type curType = inType;
do
{
FieldInfo fieldInfo = curType.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.DeclaredOnly);
if (fieldInfo != null)
{
return fieldInfo;
}
curType = curType.BaseType;
} while (curType != null);
return null;
}
public static string GetPublicPropertiesString(object obj)
{
return GetPublicPropertiesString(obj, 4096);
}
public static void SetFieldValue(object obj, string fieldName, object fieldValue)
{
FieldInfo field = GetFieldByName(obj.GetType(), fieldName);
if (field == null)
{
throw new ArgumentException(string.Format("The field {0} was not found for the object {1}", fieldName, obj.GetType().FullName));
}
field.SetValue(obj, fieldValue);
}
public static void SetFieldOrPropertyValue(object obj, MemberInfo memberInfo, object value)
{
PropertyInfo propertyInfo = (memberInfo as PropertyInfo);
if (propertyInfo != null)
{
propertyInfo.SetValue(obj, value, null);
return;
}
FieldInfo fieldInfo = (memberInfo as FieldInfo);
if (fieldInfo != null)
{
fieldInfo.SetValue(obj, value);
return;
}
throw new ArgumentException("memberInfo must be either a PropertyInfo or FieldInfo instance");
}
public static Type GetFieldOrPropertyValueType(MemberInfo memberInfo)
{
PropertyInfo propertyInfo = (memberInfo as PropertyInfo);
if (propertyInfo != null)
{
return propertyInfo.PropertyType;
}
FieldInfo fieldInfo = (memberInfo as FieldInfo);
if (fieldInfo != null)
{
return fieldInfo.FieldType;
}
throw new ArgumentException("memberInfo must be either a PropertyInfo or FieldInfo instance");
}
public static T GetFieldOrPropertyValue(object obj, MemberInfo memberInfo)
{
PropertyInfo propertyInfo = (memberInfo as PropertyInfo);
if (propertyInfo != null)
{
return (T)propertyInfo.GetValue(obj, null);
}
FieldInfo fieldInfo = (memberInfo as FieldInfo);
if (fieldInfo != null)
{
return (T)fieldInfo.GetValue(obj);
}
throw new ArgumentException("memberInfo must be either a PropertyInfo or FieldInfo instance");
}
public static T GetFieldOrPropertyValueByName(object obj, string memberName)
{
Type objectType = obj.GetType();
PropertyInfo propertyInfo = objectType.GetProperty(memberName);
if (propertyInfo != null)
{
return (T)propertyInfo.GetValue(obj, null);
}
FieldInfo fieldInfo = objectType.GetField(memberName);
if (fieldInfo != null)
{
return (T)fieldInfo.GetValue(obj);
}
throw new ArgumentException(string.Format("The object {0} does not contain a property or field with the name {1}",
objectType.FullName, memberName));
}
private static bool BuildMemberString(int maxNumChars, MemberInfo prop, object obj, StringBuilder sb)
{
ToStringQualifierAttribute qualifier = null;
if (prop.IsDefined(typeof(ToStringQualifierAttribute), false))
{
object[] qualifiers = prop.GetCustomAttributes(typeof(ToStringQualifierAttribute), false);
if (qualifiers.Length > 0)
{
qualifier = qualifiers[0] as ToStringQualifierAttribute;
if (qualifier != null)
{
if (qualifier.Ignore)
{
return true;
}
}
}
}
if (sb.Length >= maxNumChars)
{
return false;
}
if (sb.Length > 0)
{
sb.Append("; ");
}
sb.AppendFormat("{0}=\"", prop.Name);
try
{
object value;
PropertyInfo propInfo = prop as PropertyInfo;
if (prop != null)
{
value = propInfo.GetValue(obj, null);
}
else
{
value = ((FieldInfo)prop).GetValue(obj);
}
if (value == null)
{
sb.Append("null");
}
else
{
ICollection collection = value as ICollection;
if (collection != null)
{
if ((qualifier != null) && qualifier.CollectionCountOnly)
{
AppendCollectionCountString(collection, maxNumChars, sb);
}
else
{
AppendCollectionString(collection, maxNumChars, sb);
}
}
else
{
sb.Append(value.ToString());
}
}
}
catch (Exception e2)
{
sb.Append("ERROR: " + e2.Message);
}
sb.Append("\"");
return true;
}
public static string GetPublicPropertiesString(object obj, int maxNumChars)
{
if (IsCurGetPublicPropertiesStringObject(obj))
{
return "*repeat*";
}
try
{
StringBuilder sb = new StringBuilder();
if (obj == null)
{
sb.Append("null");
}
else
{
try
{
Type type = obj.GetType();
PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in properties)
{
if (!BuildMemberString(maxNumChars, prop, obj, sb))
{
break;
}
}
FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo field in fields)
{
if (!BuildMemberString(maxNumChars, field, obj, sb))
{
break;
}
}
ICollection mainCollection = obj as ICollection;
if (mainCollection != null)
{
sb.Append(" ");
AppendEnumerableString(mainCollection, maxNumChars, 16, sb);
}
}
catch (Exception e)
{
sb.Append("EXCEPTION: " + e.Message);
}
}
if (sb.Length > maxNumChars)
{
sb.Remove(maxNumChars, sb.Length - maxNumChars);
}
return sb.ToString();
}
catch (Exception)
{
return "EXCEPTION";
}
finally
{
RemoveCurGetPublicPropertiesStringObject(obj);
}
}
public static List GetPublicProperties(Type type, PropertyInfo parent)
{
List list = new List();
PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in properties)
{
if (prop.PropertyType.BaseType != null)
{
list.AddRange(GetPublicProperties(prop.PropertyType.BaseType, prop));
}
string fullname = String.Format("{0}.{1}", parent.Name, prop.Name).ToLower();
if (!list.Contains(fullname))
{
list.Add(fullname);
}
}
return list;
}
public static List GetPublicProperties(Type type)
{
List list = new List();
PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in properties)
{
string fullname = prop.Name.ToLower();
if (!list.Contains(fullname))
{
list.Add(fullname);
}
list.AddRange(GetPublicProperties(prop.PropertyType, prop));
}
return list;
}
public static void AppendCollectionString(ICollection collection, int maxNumChars,
StringBuilder sb)
{
sb.AppendFormat("Count={0} ", collection.Count.ToString());
AppendEnumerableString(collection, maxNumChars, 16, sb);
}
public static void AppendCollectionCountString(ICollection collection, int maxNumChars,
StringBuilder sb)
{
sb.AppendFormat("Count={0} ", collection.Count.ToString());
AppendEnumerableString(collection, maxNumChars, 0, sb);
}
public static void AppendEnumerableString(IEnumerable collection, int maxNumChars, int maxNumElements,
StringBuilder sb)
{
sb.Append("[");
int i = 0;
foreach (object item in collection)
{
if (sb.Length >= maxNumChars)
{
break;
}
if (i > 0)
{
sb.Append(",");
}
if (i >= maxNumElements)
{
sb.Append("...");
break;
}
else
{
sb.Append(item.ToString());
}
i++;
}
sb.Append("]");
}
public static string GetDescription(ICustomAttributeProvider obj)
{
object[] descriptionAttributes = obj.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (!CollectionUtility.IsNullOrEmpty(descriptionAttributes))
{
return ((DescriptionAttribute)descriptionAttributes[0]).Description;
}
return null;
}
public static bool IsNullableType(Type type)
{
return (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>));
}
public static Type GetNullableUnderlyingType(Type type)
{
return new NullableConverter(type).UnderlyingType;
}
///
/// Check if a string is already being generated for this object ... if so, this would cause a stack-overflow, so
/// exit the string generation code early.
///
private static bool IsCurGetPublicPropertiesStringObject(object obj)
{
try
{
if (s_CurGetPublicPropertiesStringObjects != null)
{
foreach (object testObj in s_CurGetPublicPropertiesStringObjects)
{
if (object.ReferenceEquals(obj, testObj))
{
return true;
}
}
}
else
{
s_CurGetPublicPropertiesStringObjects = new List