using System.Dynamic; using System.Reflection; // Lovingly stolen from http://exposedobject.codeplex.com/ namespace Velopack.Tests.TestHelpers; public class ExposedClass : DynamicObject { private Type m_type; private Dictionary>> m_staticMethods; private Dictionary>> m_genStaticMethods; private ExposedClass(Type type) { m_type = type; m_staticMethods = m_type .GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static) .Where(m => !m.IsGenericMethod) .GroupBy(m => m.Name) .ToDictionary( p => p.Key, p => p.GroupBy(r => r.GetParameters().Length).ToDictionary(r => r.Key, r => r.ToList())); m_genStaticMethods = m_type .GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static) .Where(m => m.IsGenericMethod) .GroupBy(m => m.Name) .ToDictionary( p => p.Key, p => p.GroupBy(r => r.GetParameters().Length).ToDictionary(r => r.Key, r => r.ToList())); } public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { // Get type args of the call Type[] typeArgs = ExposedObjectHelper.GetTypeArgs(binder); if (typeArgs != null && typeArgs.Length == 0) typeArgs = null; // // Try to call a non-generic instance method // if (typeArgs == null && m_staticMethods.ContainsKey(binder.Name) && m_staticMethods[binder.Name].ContainsKey(args.Length) && ExposedObjectHelper.InvokeBestMethod(args, null, m_staticMethods[binder.Name][args.Length], out result)) { return true; } // // Try to call a generic instance method // if (m_staticMethods.ContainsKey(binder.Name) && m_staticMethods[binder.Name].ContainsKey(args.Length)) { List methods = new List(); foreach (var method in m_genStaticMethods[binder.Name][args.Length]) { if (method.GetGenericArguments().Length == typeArgs.Length) { methods.Add(method.MakeGenericMethod(typeArgs)); } } if (ExposedObjectHelper.InvokeBestMethod(args, null, methods, out result)) { return true; } } result = null; return false; } public override bool TrySetMember(SetMemberBinder binder, object value) { var propertyInfo = m_type.GetProperty( binder.Name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); if (propertyInfo != null) { propertyInfo.SetValue(null, value, null); return true; } var fieldInfo = m_type.GetField( binder.Name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); if (fieldInfo != null) { fieldInfo.SetValue(null, value); return true; } return false; } public override bool TryGetMember(GetMemberBinder binder, out object result) { var propertyInfo = m_type.GetProperty( binder.Name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); if (propertyInfo != null) { result = propertyInfo.GetValue(null, null); return true; } var fieldInfo = m_type.GetField( binder.Name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); if (fieldInfo != null) { result = fieldInfo.GetValue(null); return true; } result = null; return false; } public static dynamic From(Type type) { return new ExposedClass(type); } }