DynamicObjectStatic.cs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.Reflection;
  6. namespace ShwasherSys.ReflectionMagic
  7. {
  8. public class DynamicObjectStatic : DynamicObjectBase
  9. {
  10. private static readonly ConcurrentDictionary<Type, IDictionary<string, IProperty>> _propertiesOnType = new ConcurrentDictionary<Type, IDictionary<string, IProperty>>();
  11. /// <summary>
  12. /// Initializes a new instance of the <see cref="DynamicObjectStatic"/> class, wrapping the specified type.
  13. /// </summary>
  14. /// <param name="type">The type to wrap.</param>
  15. /// <exception cref="ArgumentNullException">Thrown when <paramref name="type"/> is <c>null</c>.</exception>
  16. public DynamicObjectStatic(Type type)
  17. {
  18. TargetType = type ?? throw new ArgumentNullException(nameof(type));
  19. }
  20. protected override IDictionary<Type, IDictionary<string, IProperty>> PropertiesOnType => _propertiesOnType;
  21. // For static calls, we have the type and the instance is always null
  22. protected override Type TargetType { get; }
  23. protected override object Instance => null;
  24. public override object RealObject => TargetType;
  25. protected override BindingFlags BindingFlags => BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
  26. public dynamic New(params object[] args)
  27. {
  28. if (args == null)
  29. throw new ArgumentNullException(nameof(args));
  30. Debug.Assert(TargetType != null);
  31. #if NETSTANDARD1_5
  32. var constructors = TargetType.GetTypeInfo().GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  33. object result = null;
  34. for (int i = 0; i < constructors.Length; ++i)
  35. {
  36. var constructor = constructors[i];
  37. var parameters = constructor.GetParameters();
  38. if (parameters.Length == args.Length)
  39. {
  40. bool found = true;
  41. for (int j = 0; j < args.Length; ++j)
  42. {
  43. if (parameters[j].ParameterType != args[j].GetType())
  44. {
  45. found = false;
  46. break;
  47. }
  48. }
  49. if (found)
  50. {
  51. result = constructor.Invoke(args);
  52. break;
  53. }
  54. }
  55. }
  56. if (result == null)
  57. throw new MissingMethodException($"Constructor that accepts parameters: '{string.Join(", ", args.Select(x => x.GetType().ToString()))}' not found.");
  58. return result.AsDynamic();
  59. #else
  60. return Activator.CreateInstance(TargetType, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, args, null).AsDynamic();
  61. #endif
  62. }
  63. }
  64. }